Jest

speciaLLunch·2023년 3월 16일
1

TestDrivenDevelopment

목록 보기
2/5

테스트 프레임워크 중 가장 많이 쓰이고, CRA에도 기본적으로 탑재되어 React 개발환경에 최적화된 Jest 프레임워크에 대해 알아보고 환경설정 및 예제 작성도 해보았다. 이를 토대로 회사 테스트 환경 구축도 완료.


Jest

React 환경설정

  • CRA 없이 Setup
    • CRA를 통해 만든 앱은 react-test-renderer만 추가해주면 됨
    • CRA를 통해 만든 앱이 아닐 경우, babel 세팅 필요

npm install --save-dev jest babel-jest @babel/preset-env @babel/preset-react react-test-renderer

bable.config.js
module.exports = {
presets: ['@babel/preset-env', '@babel/preset-react'],
};

  • Typescript 세팅
    • Babel을 통한 ts세팅은 단순 트랜스파일링(transpilation)이기 때문에 Jest가 테스트 시 타입체크를 하지는 않음
    • 만약 타입체크가 필요하다면 ts-jest를 사용해야함

npm install --save-dev @babel/preset-typescript

bable.config.js
module.exports = {
presets: [
['@babel/preset-env', {targets: {node: 'current'}}],
'@babel/preset-typescript',
],
};

  • jest.config.ts 세팅

Mock

  • Mocking
    • 테스트를 독립시켜 의존성을 개발자가 컨트롤하고 검사할 수 있는 객체로 변환하는 기술
    • 우리가 컨트롤할 수 없는 무엇인가를 대체하는 것이 목적
    • 제공하는 기능
      • 함수 호출 capture
      • return value 설정
      • 구현 변경
  • 사용방법
  1. jest.fn()
test("returns undefined by default", () => {
  const mock = jest.fn();

  let result = mock("foo");

  expect(result).toBeUndefined();
  expect(mock).toHaveBeenCalled();
  expect(mock).toHaveBeenCalledTimes(1);
  expect(mock).toHaveBeenCalledWith("foo");
});
  • 다른 방법에 비해 잘 안쓰이는 방법
    • jest.mock 은 자동적으로 모듈의 모든 함수를 Mocking
    • jest.spyOn 도 마찬가지로 모든 함수를 Mocking 해주면서 원래의 함수를 다시 복원 가능
  1. jest.mock
  • 자동으로 모듈이 export 하는것들을 Mocking해주는 방법
  • math.js 예제
// math.js

export const add      = jest.fn();
export const subtract = jest.fn();
export const multiply = jest.fn();
export const divide   = jest.fn();

// mock.test.js

import * as app from "./app";
import * as math from "./math";

jest.mock("./math.js");

test("calls math.add", () => {
  app.doAdd(1, 2);
  expect(math.add).toHaveBeenCalledWith(1, 2);
});

test("calls math.subtract", () => {
  app.doSubtract(1, 2);
  expect(math.subtract).toHaveBeenCalledWith(1, 2);
});
  • 모듈의 원래 구현에 접근하기 어렵다는 단점 -> spyOn 사용으로 상쇄
  1. jest.spyOn
  • 모듈의 원래 구현에 가깝게 구현
  • 실제로 함수를 대체하지 않고, 특정 side effect가 발생하는지 테스트할 때 유용
import * as app from "./app";
import * as math from "./math";

test("calls math.add", () => {
  const addMock = jest.spyOn(math, "add");

  // calls the original implementation
  expect(app.doAdd(1, 2)).toEqual(3);

  // and the spy stores the calls to add
  expect(addMock).toHaveBeenCalledWith(1, 2);
});

import * as app from "./app";
import * as math from "./math";

test("calls math.add", () => {
  // store the original implementation
  const originalAdd = math.add;

  // mock add with the original implementation
  math.add = jest.fn(originalAdd);

  // spy the calls to add
  expect(app.doAdd(1, 2)).toEqual(3);
  expect(math.add).toHaveBeenCalledWith(1, 2);

  // override the implementation
  math.add.mockImplementation(() => "mock");
  expect(app.doAdd(1, 2)).toEqual("mock");
  expect(math.add).toHaveBeenCalledWith(1, 2);

  // restore the original implementation
  math.add = originalAdd;
  expect(app.doAdd(1, 2)).toEqual(3);
});
profile
web front

0개의 댓글