const getLogSpy = () => {
const logSpy = jest.spyOn(MissionUtils.Console, "print");
logSpy.mockClear();
return logSpy;
};
지난번 포스팅에 이어 이번엔 getLogSpy
함수 분석을 해보겠다. 위 함수도 우테코 프리코스 테스트 코드로 주어진 친구이다. 지난번과 같이 하나하나 분석해보자.
const logSpy = jest.spyOn(MissionUtils.Console, "print");
함수 첫 부분에 이전에 다루지 않았던 spyOn
메서드가 보인다.
jest 공식 문서를 찾아본 결과 spyOn
은 jest.fn()
과 비슷하게 mock function을 반환하지만, 인자값으로 주어진 object
의 methodName
메서드의 호출을 추가적으로 기록한다는 것을 알 수 있었다.
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));
이 부분을 자세히 보자.
처음 보는 메서드 toHaveBeenCalledWith
과 expect.stringContaining
을 볼 수 있다.
jest 공식 문서에 따르면 toHaveBeenCalledWith
메서드는 mock function이 특정 argument와 함께 호출됐었는지 확인할 수 있게 해주는 역할을 한다고 한다.
또 expect.stringContaining
메서드는 전달받은 값이 인자로 받은 string
과 일치하는지 여부를 확인해주는 역할을 한다고 한다.
종합해서 보면
logs.forEach((log) => {
expect(logSpy).toHaveBeenCalledWith(expect.stringContaining(log));
});
위 코드는 logSpy
가 logs
의 각 요소 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
에 해당하는 문자열을 포함한 채로 호출이 되었는지를 확인하는 부분이었기에 직관적으로 알아볼 수 있게 코드를 작성한 것 같다. (추측)
혹시 다른 의견이 있다면 알려주세요 ㅜㅜ 저 부분은 잘 모르겠어요