밑의 비동기 코드를 테스트하기 위해서는 무조건 6초 이상을 기다려야 한다.

export function asyncFn() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve('Done!')
    }, 6000)
  })
}

그러나 매번 테스트를 할 때마다 6초 이상의 시간을 사용해야 한다는 것은 굉장히 비효율적이다. 굳이 비동기 함수에서 비동기 작업에 할당된 시간을 모두 다 써야지만 테스트가 가능할까? 비동기 함수를 테스트할 때 드는 필요없는 시간을 최소화할 수 있는 방법이 있지 않을까?

mockResolvedValue

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)
})

Untitled

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 호출에서의 모킹 테스트

실용적으로 모킹 테스트를 사용하는 예시를 살펴보자. 가장 많이 사용하는 사례는 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')
  })
})

Untitled