Notice
Recent Posts
Recent Comments
관리 메뉴

즐겁게, 코드

프론트엔드 테스팅 세 번째 걸음 : 목업 테스팅 본문

🎨 프론트엔드/Testing

프론트엔드 테스팅 세 번째 걸음 : 목업 테스팅

Chamming2 2021. 8. 20. 01:59

목업 테스팅

지난 글에서는 비동기 동작을 테스트하는 방법을 살펴봤는데요, 테스트 코드에서 실제 DB나 API에 접근하면 테스트 코드에서 DB를 잘못 수정할 수도 있는 등 예측할 수 없는 결과를 초래할 수 있다는 문제가 있습니다.

// getData.js

function getData() {
    fetch('fetch('https://jsonplaceholder.typicode.com/todos/1')
  .then(response => response.json())
  .then(data => data)
}

예를 들어 테스트 코드에서 위와 같이 데이터를 페칭해오는 코드를 실제로 호출한다면 테스트 단계에서 API 호출 횟수를 소모하게 될 뿐만 아니라, 네트워크 사정이 좋지 않을 때는 타임아웃이 발생해 테스트를 통과하는 문제가 생기게 됩니다.

 

따라서 테스트를 수행할 때는 함수에서 실제 API를 호출하는 대신, 이를 모형화(목업)한 함수를 사용함으로써 테스트 환경과 개발 환경을 완전히 격리시킬 수 있습니다.

목업 함수

목업 함수는 해당 API와 동일한 접근 방법과 결과물을 정의해 API를 실제로 호출하지 않고도 테스팅이 가능하도록 합니다.

목업 함수를 정의하기 위해서는 먼저 해당 API가 어떤 값을 반환하는지를 파악합니다.

// GET https://jsonplaceholder.typicode.com/todos/1
{
    userId: 1,
    id: 1,
    title: "delectus aut autem",
    completed: false
}

// GET https://jsonplaceholder.typicode.com/todos/2
{
  userId: 1,
  id: 2,
  title: "quis ut nam facilis et officia qui",
  completed: false,
}

Arrange - Act - Assert (AAA) 패턴에 따라 이를 테스트 목표값으로 설정하거나, 이를 기반으로 목업 데이터셋을 생성합니다.

// 목업 데이터셋
const mockedDataList = [
  {
    userId: 1,
    id: 1,
    title: "delectus aut autem",
    completed: false,
  },
  {
    userId: 1,
    id: 2,
    title: "quis ut nam facilis et officia qui",
    completed: false,
  },
];

test("목업 함수 테스트", () => {
  // Arrange
});

다음으로 jest.fn() 함수를 통해 목업 함수를 생성합니다.
목업 함수에는 일반적인 함수처럼 인자를 전달할 수 있고, 직접 로직을 작성하거나 로직 없이 반환할 값만을 직접 지정할 수도 있습니다.

const mockedGetData = jest.fn();

이제 이 목업 함수가 fetch 를 사용한 것처럼 프라미스를 반환하도록 해보겠습니다.

 const mockedGetData = jest.fn(id).mockResolvedValue(mockedDataList[id]);

목업 함수의 메서드는 값이나 프라미스를 반환하는 등 다양한 역할을 수행할 수 있습니다.
수행 가능한 역할의 자세한 목록은 [공식 문서 API 목록] 을 참고해 주세요.

이제 데이터를 프라미스를 통해 리턴하는 목업 함수가 완성되었으니, 이전에 하던 것처럼 평가를 진행하면 됩니다.

// 목업 데이터셋
const mockedDataList = [
  {
    userId: 1,
    id: 1,
    title: "delectus aut autem",
    completed: false,
  },
  {
    userId: 1,
    id: 2,
    title: "quis ut nam facilis et officia qui",
    completed: false,
  },
];

test("목업 함수 테스트", async () => {
  // Arrange
  const id = 0;

  // 목업 함수 설정
  const mockedGetData = jest.fn(id).mockResolvedValue(mockedDataList[id]);
  const data = await mockedGetData();

  // Assert
  expect(data).toEqual(mockedDataList[id]);
});

성공입니다! 이제 실제 API가 아닌 목업 함수를 통해 테스트를 진행할 수 있게 되었습니다.

목업 모듈

목업 함수는 특정 함수의 동작을 목업으로 만든 것이었다면, 한 모듈 전체를 목업으로 만들 수도 있습니다.

목업 모듈 생성하기

먼저 목업을 만들고자 하는 모듈을 찾고, 해당 모듈이 존재하는 경로에 __mocks__ 라는 이름의 폴더를 만듭니다.

  • 폴더 이름은 반드시 __mocks__ 여야만 합니다!
/
├── __mocks__/
│ 
│
└── getData.js

다음으로 대상 모듈과 동일한 이름의 파일(모듈)을 생성합니다.

/
├── __mocks__/
│      └── getData.js
│
└── getData.js

이제 getData 목업 모듈에는 jest.fn() 을 사용해 모듈의 기능들을 목업 함수로 구성해주면 됩니다.

// 목업 데이터셋
const mockedDataList = [
  {
    userId: 1,
    id: 1,
    title: "delectus aut autem",
    completed: false,
  },
  {
    userId: 1,
    id: 2,
    title: "quis ut nam facilis et officia qui",
    completed: false,
  },
];

// 모듈 내의 목업 함수
export const getData = jest
  .fn(id)
  .mockResolvedValue(mockedDataList[id - 1]);

목업 모듈 사용하기

이제 생성한 목업 모듈을 테스트 코드로 불러와야 할텐데요, 먼저 원본 모듈을 불러옵니다.

import { getData } from "../getData.js";

그리고 jest.mock() 함수로 해당 모듈의 경로를 전달합니다.

  • 이러면 해당 경로에 __mocks__ 폴더가 존재하는지 검사하고, __mocks__ 폴더에 만들어둔 동일한 이름의 목업 모듈을 찾아 덮어쓰게 됩니다.
import { getData } from "../getData.js";
// jest.mock() 을 통해 원본 getData 모듈을 목업 모듈로 오버라이딩합니다.
jest.mock("../getData.js");

이제 불러온 목업 모듈의 함수를 기반으로 테스팅을 진행할 수 있게 됩니다!

import { getData } from "../getData.js";
jest.mock("../getData.js");

// 목업 데이터셋
const mockedDataList = [
  {
    userId: 1,
    id: 1,
    title: "delectus aut autem",
    completed: false,
  },
  {
    userId: 1,
    id: 2,
    title: "quis ut nam facilis et officia qui",
    completed: false,
  },
];

test("목업 함수 테스트", async () => {
  // Arrange
  const id = 0;

  // Act
  const data = await getData();

  // Assert
  expect(data).toEqual(mockedDataList[id]);
});

지금까지는 바닐라 자바스크립트 위에서 jest를 사용해 테스팅을 진행했습니다!
다음 글부터는 react-testing-library를 통해 리액트 어플리케이션의 테스팅을 수행해보도록 하겠습니다.

반응형
Comments
소소한 팁 : 광고를 눌러주시면, 제가 뮤지컬을 마음껏 보러다닐 수 있어요!
와!! 바로 눌러야겠네요! 😆