밑의 비동기 코드를 테스트하기 위해서는 무조건 6초 이상을 기다려야 한다.
export function asyncFn() {
return new Promise((resolve) => {
setTimeout(() => {
resolve('Done!')
}, 6000)
})
}
그러나 매번 테스트를 할 때마다 6초 이상의 시간을 사용해야 한다는 것은 굉장히 비효율적이다. 굳이 비동기 함수에서 비동기 작업에 할당된 시간을 모두 다 써야지만 테스트가 가능할까? 비동기 함수를 테스트할 때 드는 필요없는 시간을 최소화할 수 있는 방법이 있지 않을까?
import * as example from './example'
describe('async test', () => {
test('async/await', async () => {
jest.spyOn(example, 'asyncFn')
.mockResolvedValue('Done!')
const res = await example.asyncFn()
expect(res).toBe('Done?')
}, 7000)
})
7초 동안 기다릴 필요가 없이 0.4초만에 테스트가 끝났다!
일단 진실부터 이야기하자면, 이 코드는 가짜 코드이다. 밑의 코드도 통과된다는 것을 보면 알 수 있다.
import * as example from './example'
describe('async test', () => {
test('async/await', async () => {
jest.spyOn(example, 'asyncFn')
.mockResolvedValue('Done?')
const res = await example.asyncFn()
expect(res).toBe('Done?') // 원래는 Done!이 되어야 한다!
}, 7000)
})
즉, 위의 코드가 완전히 용이하다고는 볼 수 없지만, 일단은 실행하고자 하는 함수를 가짜로 만들 수 있다는 것에 집중하는 것이 좋다.
실용적으로 모킹 테스트를 사용하는 예시를 살펴보자. 가장 많이 사용하는 사례는 API 호출이다.
// example.js
import axios from "axios";
import _upperFirst from 'lodash/upperFirst'
import _toLower from 'lodash/toLower'
export async function fetchMovieTitle() {
const res = await axios.get('<https://omdbapi.com?apikey=7035c60c&i=tt4520988>') // 겨울왕국
return _upperFirst(_toLower(res.data.Title))
}
일반적으로 지금까지는 밑과 같은 방식으로 테스트 코드를 작성했을 것이다.
// example.test.js
import { fetchMovieTitle } from "./example";
describe('async test', () => {
test('change movie title', async () => {
const title = await fetchMovieTitle()
expect(title).toBe('Frozen ii')
})
})