본문 바로가기
개발/프로젝트-식당 웨이팅 앱 FOOD LINE

230621 실전프로젝트19 [Nest.js] Jest로 Unit test code 짜기

by 코딩하는짱구 2023. 6. 21.
반응형

✅오늘 학습  Keyword

프로젝트 마무리 단계에 접어들었고 CI/CD를 위한 UNIT TEST CODE 작성을 시작했다. 

 

 

✅오늘 겪은 문제

단위테스트에서 뭘 테스트하고자 하는지 헷갈려서 예전에 봤던 강의를 다시 찾아봤다.

 

단위테스트의 목적은 개별 단위가 올바르게 동작하는지를 확인하는 것이다. 

1. 입출력: 함수나 메서드에 정확한 입력을 주고, 그 결과가 예상한 출력과 일치하는지 확인(즉 함수의 동작이 올바른지 확인, 예상되는 값을 입력해주어야 한다)

2. 예외처리가 필요한 경우 예외가 필요한지, 그리고 예외처리가 올바르게 동작하는지 

3. 의존성: 단위 테스트에서는 주로 의존성을 가지는 외부 리소스나 모듈을 mocking하여 테스트한다

 

그러니까 실제 데이터베이스에 접근하여 데이터를 확인하는 것이 아니라, 데이터베이스와의 의존성을 제거하고 mocking데이터로 대체하여 함수의 '동작'만을 테스트하는 것. 

 

✅오늘 알게된 점 

nest.js 환경에서는 처음 짜보는 test code이기에 방법을 기록해둔다. 

nest.js는 내장된 종속성 주입을 사용해서 쉽게 테스트 코드를 작성할 수 있도록 도와준다. 

Jest를 기본 테스트 프레임 워크로 제공해주며 테스팅 패키지도 제공하기 때문에 @nestjs/testing 패키지를 사용하면 테스트에 사용되는 종속성만 선언해서 모듈을 만들어 사용한다. 

import { Test } from '@nestjs/testing';
import { getRepositoryToken } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Stores } from './stores.entity';
import { StoresRepository } from './stores.repository';

describe('StoresRepository', () => {
  let repository: StoresRepository;
  let storesMockRepository: Repository<Stores>;

  beforeEach(async () => {
    const module = await Test.createTestingModule({
      providers: [
        StoresRepository,
        {
          provide: getRepositoryToken(Stores),
          useClass: Repository,
        },
      ],
    }).compile();

    //repository 변수에 StoresRepository클래스의 인스턴스가 할당되어 사용할 수 있게 됌,
    //repository를 사용하여 StoryRepository의 메소드를 호출하고 test할 수 있음
    repository = module.get<StoresRepository>(StoresRepository);
    //storeMockRepository= getRepositoryToken(Stores)로 생성된 MockRepository 객체
    storesMockRepository = module.get<Repository<Stores>>(
      getRepositoryToken(Stores),
    );
  });

  //사용자 위치 기반 반경 1km내의 식당 조회를 위해 전체 데이터 조회
  describe('findAll', () => {
    it('findAll', async () => {
      const storesData: Stores[] = [
        // Mock stores data
      ];

      jest.spyOn(storesMockRepository, 'find').mockResolvedValue(storesData);

      const result = await repository.findAll();

      expect(result).toEqual(storesData);
      expect(storesMockRepository.find).toHaveBeenCalled();
    });
  });

  //1차 햄버거 조회
  describe('searchStores', () => {
    it('1차 햄버거 조회', async () => {
      const keyword = 'keyword';
      const sort = 'ASC';
      const column = 'column';
      const searchStoresData: Stores[] = [
        // Mock search stores data
      ];

      jest
        .spyOn(storesMockRepository, 'find')
        .mockResolvedValue(searchStoresData);

      const result = await repository.searchStores(keyword, sort, column);

      expect(result).toEqual(searchStoresData);
      expect(storesMockRepository.find).toHaveBeenCalled();
    });
  });

  //cycleTime 가져오기
  describe('getCycleTimeByStoreId', () => {
    it('가게의 cycletime 조회', async () => {
      const storeId = 1;
      const cycleTime = 10;
      const store = new Stores();
      store.storeId = storeId;
      store.storeName = '';
      store.description = '';
      store.category = '';
      store.maxWaitingCnt = 0;
      store.currentWaitingCnt = 0;
      store.La = 0;
      store.Ma = 0;
      store.address = '';
      store.distance = 0;
      store.oldAddress = '';
      store.cycleTime = cycleTime;
      store.tableForTwo = 0;
      store.tableForFour = 0;
      store.rating = 0;
      store.coordinates = null;
      store.createdAt = new Date();
      store.updatedAt = new Date();
      store.waitings = [];
      store.reviews = [];
      store.tables = null;
      store.user = null;

      jest.spyOn(storesMockRepository, 'findOne').mockResolvedValue(store);

      const result = await repository.getCycleTimeByStoreId(storeId);

      expect(result).toEqual(cycleTime);
      expect(storesMockRepository.findOne).toHaveBeenCalledWith({
        where: { storeId },
      });
    });
  });

  //한개 찾기
  describe('findStoreById', () => {
    it('한개 찾기', async () => {
      const storeId = 1;
      const store = new Stores();
      store.storeId = storeId;
      store.storeName = '';
      store.description = '';
      store.category = '';
      store.maxWaitingCnt = 0;
      store.currentWaitingCnt = 0;
      store.La = 0;
      store.Ma = 0;
      store.address = '';
      store.distance = 0;
      store.oldAddress = '';
      store.cycleTime = 0;
      store.tableForTwo = 0;
      store.tableForFour = 0;
      store.rating = 0;
      store.coordinates = null;
      store.createdAt = new Date();
      store.updatedAt = new Date();
      store.waitings = [];
      store.reviews = [];
      store.tables = null;
      store.user = null;

      jest.spyOn(storesMockRepository, 'findOne').mockResolvedValue(store);
      const result = await repository.findStoreById(storeId);

      expect(result).toEqual(store);
      expect(storesMockRepository.findOne).toHaveBeenCalledWith({
        where: { storeId },
      });
    });
  });
});

 

#jest.spyOn()사용법

jest.spyOn 함수는 테스트 중에 객체의 메소드를 가로채서 해당 메소드의 동작을 변경하고 모의(mock)값을 반환한다.

 

#test fail내역 뿐만 아니라 성공 내역도 보고싶을때

--verbose 설정

 

반응형