Mock

  • 모의 함수는 함수의 실제 구현을 제거하고 함수 호출, 전달된 매개변수, 생성자 | 함수 인스턴스 등을 캡처하며 테스트 시 반환 값을 설정할 수 있게 한다.

  • 모의 함수는 코드 간의 연결을 테스트하는 데 사용된다.

Mock 사용 유형

  • 테스트 코드에서 사용할 모의 함수를 생성

  • 모듈 종속성을 재정의하기 위해 수동 모의를 작성

Mock 속성

  • 모든 모의 함수에는 .mock 속성이 있으며, 이 속성은 함수 호출 방식, 반환 값, this 값등을 저장한다.

  • mock.instances, mock.contexts, mock.calls, mock.results 등 다양한 속성을 통해 호출 정보를 검사할 수 있다.

const myMock1 = jest.fn();
const a = new myMock1();
console.log(myMock1.mock.instances);
// > [ <a> ]

const myMock2 = jest.fn();
const b = {};
const bound = myMock2.bind(b);
bound();
console.log(myMock2.mock.contexts);
// > [ <b> ]

Mock 반환 값

  • mock은 테스트 중 코드에 테스트 값을 주입하는 데도 사용할 수 있다.

const myMock = jest.fn();
console.log(myMock());
// > undefined

myMock.mockReturnValueOnce(10).mockReturnValueOnce("x").mockReturnValue(true);

console.log(myMock(), myMock(), myMock(), myMock());
// > 10, 'x', true, true

[2] 이해 못함

모듈 Mock

  • 외부 모듈 (예: Axios)을 모의하여 실제 API 호출 없이 테스트할 수 있다.

  • jest.mock 함수를 사용하여 모듈을 모의하고, 필요한 반환 값을 설정한다.

import axios from "axios";
import Users from "./users";

jest.mock("axios");

test("사용자를 가져와야 합니다", () => {
  const users = [{ name: "Bob" }];
  const resp = { data: users };
  axios.get.mockResolvedValue(resp);

  // 또는 다음을 사용할 수 있습니다. 사용 사례에 따라 다릅니다:
  // axios.get.mockImplementation(() => Promise.resolve(resp))

  return Users.all().then((data) => expect(data).toEqual(users));
});

부분 Mock !!!!!!!!!!!

  • 모듈의 일부만 Mock하고, 나머지는 실제 구현을 유지한다.

  • jest.requireActual을 사용하여 실제 모듈의 나머지 부분을 유지하면서 특정 부분만 모의한다.

export const foo = "foo";
export const bar = () => "bar";
export default () => "baz";
//test.js
import defaultExport, { bar, foo } from "../foo-bar-baz";

jest.mock("../foo-bar-baz", () => {
  const originalModule = jest.requireActual("../foo-bar-baz");

  // 기본 내보내기와 'foo'라는 명명된 내보내기를 모의합니다.
  return {
    __esModule: true,
    ...originalModule,
    default: jest.fn(() => "mocked baz"),
    foo: "mocked foo",
  };
});

test("부분 모의 테스트", () => {
  const defaultExportResult = defaultExport();
  expect(defaultExportResult).toBe("mocked baz");
  expect(defaultExport).toHaveBeenCalled();

  expect(foo).toBe("mocked foo");
  expect(bar()).toBe("bar");
});

export와 export default 모듈은 mock 방법이 다른 부분을 모르고 export 방식으로 통일하여 오류가 발생

Mock 완전 구현

모의 함수의 구현을 완전히 교체해야 하는 경우가 있다.

  • jest.fn 또는 mock 함수의 mockImplementationOnece, mockImplementation을 사용하여 Mock 함수의 구현을 설정할 수 있다.

  • 이는 복잡한 동작을 재현하거나 여러 호출에 대해 다른 결과를 생성해야 할 때 유용하다.

Jest.fn

const myMockFn = jest.fn((cb) => cb(null, true));

myMockFn((err, val) => console.log(val));
// > true

mockImplementation

module.exports = function () {
  // 일부 구현;
};
jest.mock("../foo"); // 자동 모의로 자동으로 발생합니다.
const foo = require("../foo");

// foo는 모의 함수입니다.
foo.mockImplementation(() => 42);
foo();
// > 42

: mockImplementationOnce로 정의된 구현을 모두 소진하면 jest.fn으로 설정된 기본 구현이 실행된다.

const myMockFn = jest
  .fn(() => "default")
  .mockImplementationOnce(() => "first call")
  .mockImplementationOnce(() => "second call");

console.log(myMockFn(), myMockFn(), myMockFn(), myMockFn());
// > 'first call', 'second call', 'default', 'default'

체이닝된 메서드 모의

  • 체이닝된 메서드는 mockReturnThis()를 사용하여 this를 반환하도록 설정할 수 있다.

const myObj = {
  myMethod: jest.fn().mockReturnThis(),
};

// 다음과 동일합니다.

const otherObj = {
  myMethod: jest.fn(function () {
    return this;
  }),
};

Mock 이름

  • mockName 메서드를 사용하여 모의 함수에 이름을 설정할 수 있으며, 이는 테스트 오류 출력에서 유용하다.

const myMockFn = jest
  .fn()
  .mockReturnValue("default")
  .mockImplementation((scalar) => 42 + scalar)
  .mockName("add42");

사용자 정의 매처

  • mock 함수 호출 방식을 단언하기 위한 사용자 정의 매처 함수가 있다.

  • toHaveBeenCalled, toHaveBeenCalledWith, toHaveBeenLastCalledWith,toMatchSnapshot등을 사용하여 함수 호출을 검사할 수 있다.

// 모의 함수가 한 번 이상 호출되었는지 확인
expect(mockFunc).toHaveBeenCalled();

// 모의 함수가 지정된 인수로 한 번 이상 호출되었는지 확인
expect(mockFunc).toHaveBeenCalledWith(arg1, arg2);

// 모의 함수의 마지막 호출이 지정된 인수로 호출되었는지 확인
expect(mockFunc).toHaveBeenLastCalledWith(arg1, arg2);

// 모든 호출과 모의 이름이 스냅샷으로 기록되었는지 확인
expect(mockFunc).toMatchSnapshot();

Last updated