우테코 테스트 코드로 본 Jest mock function - 3

김영우·2022년 11월 12일
1
post-thumbnail

getLogSpy 함수

const getLogSpy = () => {
  const logSpy = jest.spyOn(MissionUtils.Console, "print");
  logSpy.mockClear();
  return logSpy;
};

지난번 포스팅에 이어 이번엔 getLogSpy함수 분석을 해보겠다. 위 함수도 우테코 프리코스 테스트 코드로 주어진 친구이다. 지난번과 같이 하나하나 분석해보자.


const logSpy = jest.spyOn(MissionUtils.Console, "print");

함수 첫 부분에 이전에 다루지 않았던 spyOn 메서드가 보인다.

jest 공식 문서를 찾아본 결과 spyOnjest.fn()과 비슷하게 mock function을 반환하지만, 인자값으로 주어진 objectmethodName 메서드의 호출을 추가적으로 기록한다는 것을 알 수 있었다.

logSpy.mockClear();

두번째 줄이다. 이번에도 처음 다루는 mockClear 메서드가 보인다.

jest 공식 문서를 찾아본 결과 mockClear는 mock function에 대해 기록한 내용들을 모두 리셋하는 기능을 하는 것으로 보인다. 아마도 spyOn을 통해 기록하던 내용들에 대해 기록을 중지하는 기능을 가지고 있는 것 같다. (이 부분은 확실하지 않다)

getLogSpy함수는 위 두 과정을 거쳐 logSpy를 반환한다.

test("기능 테스트", () => {
  mockRandoms([
    [8, 21, 23, 41, 42, 43],
    [3, 5, 11, 16, 32, 38],
    [7, 11, 16, 35, 36, 44],
    [1, 8, 11, 31, 41, 42],
    [13, 14, 16, 38, 42, 45],
    [7, 11, 30, 40, 42, 43],
    [2, 13, 22, 32, 38, 45],
    [1, 3, 5, 14, 22, 45],
  ]);
  mockQuestions(["8000", "1,2,3,4,5,6", "7"]);
  const logs = [
    "8개를 구매했습니다.",
    "[8, 21, 23, 41, 42, 43]",
    "[3, 5, 11, 16, 32, 38]",
    "[7, 11, 16, 35, 36, 44]",
    "[1, 8, 11, 31, 41, 42]",
    "[13, 14, 16, 38, 42, 45]",
    "[7, 11, 30, 40, 42, 43]",
    "[2, 13, 22, 32, 38, 45]",
    "[1, 3, 5, 14, 22, 45]",
    "3개 일치 (5,000원) - 1개",
    "4개 일치 (50,000원) - 0개",
    "5개 일치 (1,500,000원) - 0개",
    "5개 일치, 보너스 볼 일치 (30,000,000원) - 0개",
    "6개 일치 (2,000,000,000원) - 0개",
    "총 수익률은 62.5%입니다.",
  ];
  const logSpy = getLogSpy();
  const app = new App();
  app.play();
  logs.forEach((log) => {
    expect(logSpy).toHaveBeenCalledWith(expect.stringContaining(log));
  });
});

위 코드는 getLogSpy를 사용한 예시이다. 우테코 5기 프리코스 3주차 미션의 테스트 코드에서 발췌했다. 코드의 마지막 부분을 보면

const logSpy = getLogSpy();

위와 같이 getLogSpy함수를 통해 logSpy를 생성하는 부분을 찾아볼 수 있다.

const app = new App();
app.play();

그후 App클래스의 인스턴스를 생성하여 play메서드를 실행하고

logs.forEach((log) => {
  expect(logSpy).toHaveBeenCalledWith(expect.stringContaining(log));
});

expect를 통해 테스트를 진행한다.


expect(logSpy).toHaveBeenCalledWith(expect.stringContaining(log));

이 부분을 자세히 보자.

처음 보는 메서드 toHaveBeenCalledWithexpect.stringContaining을 볼 수 있다.

jest 공식 문서에 따르면 toHaveBeenCalledWith 메서드는 mock function이 특정 argument와 함께 호출됐었는지 확인할 수 있게 해주는 역할을 한다고 한다.

expect.stringContaining 메서드는 전달받은 값이 인자로 받은 string과 일치하는지 여부를 확인해주는 역할을 한다고 한다.


종합해서 보면

logs.forEach((log) => {
  expect(logSpy).toHaveBeenCalledWith(expect.stringContaining(log));
});

위 코드는 logSpylogs의 각 요소 log와 함께 호출되는지 테스트 해보는 코드이다.

따라서 앞선 모든 내용을 종합해봤을 때 getLogSpy 함수는 MissionUtils.Console.print 메서드가 원하는 정답값을 정확히 출력하는지 확인하기 위해 mock function 객체 logSpy를 생성하는 역할을 하는 함수이다.


여기서 의문이 하나 생겼다. MissionUtils.Console.print 자체를 jest.fn()을 이용하여 mock function으로 만들고, 이를 logSpy 대신 expect에 넣어주면 테스트를 통과할 수 있을까? (애초에 toHaveBeenCalledWith 메서드가 특정 함수가 어떤 argument와 함께 호출 됐었는지를 판별하는 함수니까...?)

흠.. 아주 잘 돌아간다. 여기서 또 한번의 의문이 생겼다. 만약 expect.stringContaining(log)가 아니라 그냥 log만 넣어주어도 테스트를 통과할 수 있을까?

흠... 이것도 아주 잘 돌아간다. 아마도 expect.stringContaining(log) 부분은 Console.print메서드가 log에 해당하는 문자열을 포함한 채로 호출이 되었는지를 확인하는 부분이었기에 직관적으로 알아볼 수 있게 코드를 작성한 것 같다. (추측)

혹시 다른 의견이 있다면 알려주세요 ㅜㅜ 저 부분은 잘 모르겠어요


다음 포스팅에는 지금까지 분석한 내용을 토대로 3주차 중간 과정에 발생한 어려움에 대해 이야기해보겠다.
profile
불편한 일들을 개발로 풀어내고 싶은 프론트엔드 개발자입니다!

0개의 댓글