[NestJS] Unit Test

hahaha·2021년 8월 3일
0

NestJS

목록 보기
8/11
post-thumbnail

Test

"TDD (테스트 주도 개발)은 필수다." 라는 말은 많이 들었지만,
실무에서 테스트 코드를 처음 작성해보며 공부한 내용을 소개한다.
아직은 개발 후 테스트 코드를 작성하고 있지만 테스트 코드를 먼저 짜고 개발을 하는 날이 오길 바라며...

  • 기본 테스트 프레임워크로 Jest를 제공한다.
    -> 테스트 실행자 역할을 하면서 모의(mocking), 감시(spying) 등에 도움되는 함수 및 유틸리티를 제공한다.
  • 테스트 파일은 테스트 대상 클래스 근처에 위치하는 것이 좋음
  • 파일명은 .spec or .test 접미사를 추가한다.
    ex) cats.controller.ts -> cats.controller.spec.ts

Mocking

  • 단위 테스트 작성 시, 해당 코드가 의존하는 부분을 가짜(mock)로 대체하는 기법
  • 테스트하려는 코드가 의존하는 부분을 직접 구현하기 부담스러울 때 사용
    ex) controller 테스트할 때, service 단의 함수가 포함된 경우 해당 함수를 모킹한다.

jest.fn()

  • 가짜 함수(mock function)를 생성
  • 함수를 mock 함수로 재할당
  • 이후 재할당된 함수는 원래의 함수 대신 mock 함수가 호출됨

jest.spyOn()

  • 기존 함수 구현은 보존하면서 mocking하는 방식
  • 해당 함수의 호출 여부와 어떻게 호출되었는지만을 알아내야할 때 사용

mockFn.mockResolvedValue( ... )

  • 모의 함수의 반환값을 설정

mockFn.mockImplementation( ... )

  • 모의 구현으로 필요한 부분 정의
  • 다른 모듈로 부터 생성된 mock 함수의 기본 구현을 정의할 때 유용

(격리된/기본) 테스트

// cats.controller.spec.ts
describe('CatsController', () => {
  let catsController: CatsController;
  let catsService: CatsService;

  beforeEach(() => {
    catsService = new CatsService();
    catsController = new CatsController(catsService);
  });

  describe('findAll', () => {
    it('should return an array of cats', async () => {
      const result = ['test'];
      jest.spyOn(catsService, 'findAll').mockImplementation(() => result);

      expect(await catsController.findAll()).toBe(result);
    });
  });
});
  • Nest와 관련된 것은 테스트하지 않음
  • 실제 의존성 주입을 사용하지 않음
  • 프레임워크와 독립적이므로 격리된 테스트라고 불림

- beforeEach / afterEach

: 각 테스트가 실행되기 전/후로 반복적으로 실행됨

- beforeAll / afterAll

: 모든 테스트가 실행되기 전/후로 한 번만 실행됨

(보다 강력한) 테스트 (with @nestjs/tesing)

// cats.controller.spec.ts
describe('CatsController', () => {
  let catsController: CatsController;
  let catsService: CatsService;

  beforeEach(async () => {
    const moduleRef = await Test.createTestingModule({
        controllers: [CatsController],
        providers: [CatsService],
      }).compile();

    catsService = moduleRef.get<CatsService>(CatsService);
    catsController = moduleRef.get<CatsController>(CatsController);
  });

  describe('findAll', () => {
    it('should return an array of cats', async () => {
      const result = ['test'];
      jest.spyOn(catsService, 'findAll').mockImplementation(() => result);

      expect(await catsController.findAll()).toBe(result);
    });
  });
});

createTestingModule()

  • @Module 에 전달하는 동일한 객체
  • 모듈 메타데이터 객체를 인수로 사용
  • 테스트에 사용되는 종속성만 선언하여 모듈 생성 가능

compile()

  • 의존성 있는 모듈을 부트스트랩한다.
  • 테스트할 준비가 된 모듈을 반환
  • 비동기 메서드이므로 기다려야 함
profile
junior backend-developer 👶💻

0개의 댓글