-
Jest - Jest Object1 (jest.spyOn( ))FrameWork/Jest 2023. 3. 10. 15:43
Jest Object
jest.spyOn( )
mocking에는 스파이(spy)라는 개념이 있다. 테스트를 작성할 때, 어떤 객에에 속한 함수의 구현을 가짜로 대체하지 않고, 해당 함수의 호출 여부와 어떻게 호출 되었는지만 알아내야 할 때가 있다. 이럴 때, Jest에서 제공하는 jest.spyOn(object,methodName)함수를 사용하면 된다.
실제 구현 함수1
obj.js
const calculator = { add: (a, b) => a + b, }; module.exports = calculator;
obj.test.js
const calculator = require("../../lib/obj"); describe("Jest Object jest.spyOn() ", () => { test("spying", () => { const spyFn = jest.spyOn(calculator, "add"); const result = calculator.add(2, 3); expect(spyFn).toBeCalledTimes(1); expect(spyFn).toBeCalledWith(2, 3); expect(result).toBe(5); }); });
위 코드를 보면 jest.spyOn( )함수를 이용해서 calculator객체의 add라는 함수에 스파이를 붙였다. 따라서 sypFn은 calculator 객체에 add메서드에 대한 호출횟수와 호출 시 들어간 인자 값을 알 수있다. 하지만 add메서드를 가짜 함수로 대체한 것은 아니기 때문에 결과 값은 원래 구현대로 2와 3의 합인 5가 되는 것을 확인할 수 있다.
실제 구현 함수2
userService.js
const axios = require("axios"); const API_ENDPOINT = "https://jsonplaceholder.typicode.com"; exports.findOne = function findOne(id) { return axios .get(`${API_ENDPOINT}/users/${id}`) .then((response) => response.data); };
user4.test.js
const userService = require("../../service/userService"); test("FindOne returns a user", async () => { const user = await userService.findOne(1); expect(user).toHaveProperty("id", 1); expect(user).toHaveProperty("name", "Leanne Graham"); });
우선 mocking 없이 findOne()의 결과 값에 대한 단순한 테스트를 작성한다.
외부 모듈에 jest.spyOn( )사용해서 특정 메서드 spy하기 🧐
test("findOn ftches data from the API endpoint", async () => { const spyGet = jest.spyOn(axios, "get"); await userService.findOne(1); expect(spyGet).toBeCalledTime(1); expect(spyGet).toBeCalledWith(`https://jsonplaceholder.typicode.com/user/1`); });
findOne()함수가 외부 API연동을 통해서 사용자 정보를 조회하는지 테스트 하려면 jest.spyOn()을 활용해서 axios의 get메서드를 spy하므로써 해당 메서드가 몇번 불러 와지고, 어떤 인자와 함께 불려지는지 확인하는 matcher를 사용해서 확인 할수 있다.
하지만 위 코드의 테스트는 API서버가 다운된 상황이거나 Network가 단절된 환경에서 실행하면 오류가 발생하고 코드 이외의 이유로인해 테스트가 실패하게 된다. 따라서 위 두개의 테스트 함수는 "테스트 deterministic 해야한다.(언제 실행되는 항상 같은 결과를 내야한다.)"라는 원칙에 위배된다. unit 테스트가 단독으로 고립되어 있지 않고, 외부 환경에 의존적이기 때문이다.
*deterministic : 결정론적 시스템, 결정론적 알고리즘을 의미 한다.
이 문제를 해결하려면, axios 객제의 get 메서드가 항상 같은 결과를 반환하도록 mocking해야 한다.
Return 결과 mocking
test("findOne returns what axios get returns", async () => { axios.get = jest .fn() .mockResolvedValue({ data: { id: 1, name: "surge100" } }); const user = await userService.findOne(1); expect(user).toHaveProperty("id", 1); expect(user).toHaveProperty("name", "surge100"); });
앞서 언급한 문제를 해결하려면, axios객체의 get 메서드가 항상 동일한 결과를 반환하도록 mocking해야한다. 즉, 위 코드와 같이 axios.get()를 어떤 고정된 결과 값을 return하는 가짜함수로 대체해주면된다.
'FrameWork > Jest' 카테고리의 다른 글
Jest - Testing2 (0) 2023.03.20 Jest - Module Function2 (mock implementations, mock Name) (0) 2023.03.09 Jest - Mock Function1 (모듈 mocking jest.fn( ), jest.mock( )) (0) 2023.03.09 Jest - beforeEach (0) 2023.03.06 Jest - create( ) - node-mock-http (0) 2023.03.06