Mock 함수는 새로운 함수를 구현한 게 아니라 테스트를 위해 구현하는 가짜함수이다.
가짜로 대체하는 이유
-테스트 하고 싶은 기능이 다른 기능과 엮여있을 경우 정확한 테스트를 하기 힘들다.
-내가 작성한 코드의 문제인지 api의 문제인지 db의 문제인지 다른 문제인지 파악하기 힘들다.
=>실제로 데이터베이스에 데이터를 넣지 않고 잘 작동한다는 전제하에 테스트를 하기 위해 mock이 필요하다
1. calls (호출확인)
Jest는 에서는 가짜 mock 함수를 생성할 수 있는 jest.fn()을 제공한다.
mock 함수에는 mock이라는 property가 있으며 이 안에는 calls라는 배열이 있다.
mock property에는 호출되었던 값들이 저장된다.
calls를 이용하면 함수가 총 몇번 호출 되었는 지, 호출될때 전달된 인수가 무엇인지 확인할 수 있다.
const mockFn = jest.fn();
mockFn();
mockFn(1);
describe("mock test", () => {
test("mock.calls", () => {
console.log(mockFn.mock.calls);
expect(1).toBe(1);
});
test("호출된 횟수", () => {
expect(mockFn.mock.calls.length).toBe(2);
});
test("두번째로 전달된 인수는 1", () => {
expect(mockFn.mock.calls[1][0]).toBe(1);
});
});
mock 함수를 이용하면 실제 함수를 작성하지 않고 테스트를 먼저 진행해 볼 수 있다.
const mockFn = jest.fn();
function arrForEach(arr) {
arr.forEach((num) => mockFn(num + 1));
}
arrForEach([1, 2, 3]);
describe("mock test", () => {
test("호출된 횟수", () => {
expect(mockFn.mock.calls.length).toBe(3);
});
test("두번째 호출된 값은 3", () => {
expect(mockFn.mock.calls[1][0]).toBe(3);
});
});
1.1. 호출 관련 matcher
toBeCalled = toHaveBeenCalled 호출됐나
toBeCalledTimes(times) = toHaveBeenCalledTimes(times) 몇번 호출됐나
const mockFn = jest.fn();
test("호출 됨?", () => {
//아직 호출 안 됨?
expect(mockFn).not.toBeCalled();
mockFn();
expect(mockFn).toBeCalled();
mockFn();
expect(mockFn).toBeCalledTimes(2);
});
toBeCalledWith 특정 인수를 받았는 지
lastCalledWith 마지막 인수로 특정 인수로 받았는 지
const mockFn = jest.fn();
mockFn(1);
mockFn(3);
test("인수를 뭘로 받음?", () => {
//1을 인수로 받았는 지?
expect(mockFn).toBeCalledWith(1);
//마지막 인수는 3으로 받았는 지?
expect(mockFn).lastCalledWith(3);
});
2. mockImplemetation
모의 함수의 동작을 임의로 구현하는 함수이다. 실제 원본 함수의 기능을 대체할 수 있다.
//원본 함수
function add(a,b){
retrun a + b;
}
//모의 함수
const mockFn = jest.fn();
mockFn.mockImplementation((a, b) => a + b);
mockFn(1, 2); //3
더 편하게 줄여쓸 수도 있다
const mockFn = jest.fn((a, b) => a + b);
mockFn(1, 2); //3
3. results(결과확인)
모의 함수가 어떻게 동작해야하는 지 정의하고 호출된 후 반환된 결과를 확인할 때 사용한다.
const mockFn = jest.fn((a, b) => a + b);
mockFn(1, 2);
test("returnValue", () => {
console.log(mockFn.mock.results);
expect(mockFn.mock.results[0].value).toBe(3);
});
4. mockReturnValue / mockReturnValueOnce
mockReturnValue 는 모의 함수가 호출될 때마다 지정된 값을 반환하도록 설정한다.
const mockFn = jest.fn((a, b) => a + b);
mockFn.mockReturnValue(100);
mockFn(1, 2);
test("returnValue", () => {
//fail, value는 100임
expect(mockFn.mock.results[0].value).toBe(3);
});
여러번 호출해도 항상 동일한 값이 나온다.
const mockFn = jest.fn();
mockFn.mockReturnValue(100);
mockFn();
mockFn(1);
mockFn(100);
mockReturnValueOnce는 모의 함수가 처음 호출될 때 지정된 값을 반환하고
다음 호출에는 원래 함수의 동작에 따라 값을 반환한다.
const mockFn = jest.fn((num) => num + 1);
mockFn.mockReturnValueOnce(100);
mockFn(1);
mockFn(1);
mockFn(100);
const mockFn = jest.fn((num) => num + 1);
mockFn.mockReturnValueOnce(100).mockReturnValue(200);
mockFn(1);
mockFn(1);
mockFn(100);
5. mockResolvedValue
mockResolvedValue 로 promise를 반환하는 비동기 함수의 결과값을 설정할 수 있다.
const mockFn = jest.fn();
mockFn.mockResolvedValue({ name: "감자" });
test("비동기 테스트", () => {
mockFn().then((res) => {
expect(res.name).toBe("감자");
});
});
6. mocking module
api 연동 작업 시 실제로 db에 값을 생성했다가 지우기 보단 mocking module(모의화된 모듈)을 써서 테스트를 진행할 수 있다.
먼저, mocking module을 사용하지 않는 경우,
fn에 유저를 생성해주는 함수가 있다고 가정하고
createUser: (name) => {
console.log("userDB에 사용자를 생성해주는 함수.");
return {
name,
};
},
테스트를 하면
const fn = require("./fn");
test("유저 생성", () => {
const user = fn.createUser("감자");
expect(user.name).toBe("감자");
});
실제로 userDB에 사용자를 생성해주는 함수가 실행돼서 console.log 메세지가 찍혔다.
실제로 db에 유저정보를 생성하지 않을려면 모듈을 모의화(mocking)해서 테스트를 진행할 수 있다.
모의화를 하면 실제 createUser 함수는 호출되지 않는다.
const fn = require("./fn");
jest.mock("./fn");
fn.createUser.mockReturnValue({ name: "감자" });
test("유저 생성", () => {
const user = fn.createUser("감자");
expect(user.name).toBe("감자");
});
참고
https://jestjs.io/docs/mock-function-api#jestmockt
https://inpa.tistory.com/entry/JEST-%F0%9F%93%9A-%EB%AA%A8%ED%82%B9-mocking-jestfn-jestspyOn
https://www.youtube.com/watch?v=9xBjErtlr1o&list=RDCMUCxft4RZ8lrK_BdPNz8NOP7Q&index=3
'Web > JEST' 카테고리의 다른 글
JEST - snapshot (1) | 2023.12.07 |
---|---|
JEST - before, after, only, skip (0) | 2023.12.05 |
JEST - Matcher (2) | 2023.12.05 |