포시코딩

2월27일 - Nest.js에서 jest로 테스트 코드 작성하기 본문

TIL

2월27일 - Nest.js에서 jest로 테스트 코드 작성하기

포시 2023. 2. 27. 22:11
728x90

개요

Controller - Service - Repository의 형태의 아키텍쳐로 이루어진 
Nest.js 프로젝트에서 jest로 테스트 코드를 작성하려는데

아주 기본적인 틀만 가지고도 에러가 발생해 

그 해결 과정에 대해 정리해보고자 한다.

 

일단 원래 보통 service에서 repository를 바로 inject 해오기 때문에 

repository class가 따로 필요 없으나 

 

여러 테이블을 join하거나 transaction을 쓰기에는 따로 구분 짓는 게 편하다고 생각해 

custom repository를 만들게 되었다.

 

아래는 해당 repository의 코드다.

 

Repository

// ...import 생략
@Injectable()
export class MeetupsRepository extends Repository<Meetup> {
  constructor(private dataSource: DataSource) {
    super(Meetup, dataSource.createEntityManager());
  }

  async getMeetups(): Promise<Meetup[]> {
    // ...생략
  }

대충 이런 형태고 

기본틀로 만든 테스트 코드는 다음과 같다. 

 

repository.spec.ts

// ...import 생략
describe('MeetupsService', () => {
  let repository: MeetupsRepository;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [MeetupsRepository],
    }).compile();

    repository = module.get<MeetupsRepository>(MeetupsRepository);
  });

  it('should be defined', () => {
    expect(repository).toBeDefined();
  });
});

 

nest 명령어로 service를 만들 때 자동으로 만들어지는 service.spec.ts에서

service -> repository로 바꾼 것 뿐이다.

 

이제 내가 겪은 에러들과 그 해결 방법에 대해 하나하나 알아보자

 

문제 발생

Cannot find module ~ entity

entity의 경로를 찾지 못해 발생하는 에러다. 

경로를 찾아가면

 

join.entity.ts에서 User를 가리키는 위치를 찾을 수 없다고 나온다. 

이에 대해 검색하면 다들 절대 경로를 상대 경로로 바꾸라는 말을 할 것이다. 

실제로 상대 경로로 바꿀 시 해결이 되긴 한다.

하지만 User뿐만 아니라 모든 module에서의 entity 경로를 상대경로로 죄다 바꿔줘야 한다. 

 

이건 분명 잘못된 거고 다른 해결 방법이 있을 것이라 생각했다.

 

해결 방법

https://stackoverflow.com/questions/63865678/nestjs-test-suite-failed-to-run-cannot-find-module-src-article-article-entity

 

NestJS - Test suite failed to run Cannot find module 'src/article/article.entity' from 'comment/comment.entity.ts'

i need help with nestjs and jest testing. I am new to NestJS and i got stuck on Cannot find module error when i run tests. I am trying to test my service and when i run tests i have received error

stackoverflow.com

 

역시 package.json에서 jest에 대해 moduleNameMapper 옵션을 통해 해결할 수 있었다.

package.json

{
  // ...생략
  "jest": {
    // ...생략
    "moduleNameMapper": {
      "^src/(.*)$": "<rootDir>/$1"
    }
  }
}

이렇게 변경 시 절대 경로에 대해서도 잘 작동하는 걸 볼 수 있다.

 

Nest can't resolve dependencies

위의 문제를 해결했지만 이번엔 다른 에러가 뜬다. 

대충 종속성을 확인할 수 없다는 건데 

이 문제를 해결하는데 진짜 오래 걸렸다.. 처음 해보니 뭐가 문제인지도 모르겠고 

검색해 봐도 다 헛다리 짚고 있어서..

 

결론만 얘기하자면 그럼에도 결국 방법을 찾아냈고 해결할 수 있었는데 아래를 확인

 

해결 방법

 

DataSource와 관련해서 찾지 못하고 있으니

처음엔 해당 repository를 providers에 설정한 module의 import를 가져다 썼는데 그래도 안돼서

아예 근본적인 app.module의 import를 가져다 써보니 잘 되는 것을 확인할 수 있었다!

 

그중에서 위 사진의 빨간 네모 친 TypeOrmModule과 ConfigModule(TypeOrmModule에 필요하니)

두 모듈을 import 하면 해결된다.

 

repository.spec.ts

// ...import 생략
describe('MeetupsService', () => {
  let repository: MeetupsRepository;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      imports: [
        ConfigModule.forRoot({ isGlobal: true }),
        TypeOrmModule.forRootAsync({ useClass: TypeOrmConfigService }),
      ],
      providers: [MeetupsRepository],
    }).compile();

    repository = module.get<MeetupsRepository>(MeetupsRepository);
  });

  it('should be defined', () => {
    expect(repository).toBeDefined();
  });
});

 

근데 저 노란 글씨가 거슬린다.. 이것도 해결해 보자

 

A worker process has failed to exit gracefully and has been force exited

작업 프로세스가 정상 종료 되지 않아 강제 종료 시켰다는 건데

좀 찾아본 결과 유추해 보면 테스트 실행 시 매 테스트 파일마다

DB를 새로 불러오는 코드로 작성되어 발생하는 것으로 보인다.

 

이것도 옵션을 통해 간단히 해결 가능하다.

 

해결 방법

jest를 실행할 때 --runInBand 옵션을 줄 수 있는데

해당 옵션의 역할은 테스트 실행 시 새로운 프로세스를 만들지 않고 

처음 만들어진 프로세스에서 계속 테스트를 실행하게 한다는 것 같다. 

적용해 보자.

 

package.json

"test:watch": "jest --watch  --runInBand"

기존 유닛 테스트를 실행하는 명령어 맨 뒤에 --runInBand만 추가로 붙여주면 된다.

 

이제 어떠한 에러 없이 테스트가 통과되는 걸 확인할 수 있다.

 

추가 기록사항

Nest.js에서 Jest를 통한 테스트 코드 작성에 대해 

비슷하면서도 다른 스타일의 가이드를 찾아 기록을 남긴다.

두 테스트 코드 모두 써봤는데 문제없이 잘 돌아가는 것을 확인

 

https://dev.to/tkssharma/unit-testing-and-integration-testing-nestjs-application-4d7a

 

Unit Testing and Integration Testing Nestjs Application

We will use Jest as Runner for Running tests for NestJS Lets first talk about Jest a...

dev.to

https://medium.com/@exfabrica/nestjs-unit-and-e2e-tests-with-jest-825ba5033c6

 

NestJS: Unit and E2E tests with Jest

Welcome back!

medium.com

 

여기도 설명이 괜찮아 추천

https://velog.io/@1yongs_/NestJS-Testing-Jest

 

NestJS Testing (Jest)

NestJS와 Database와 연결하여 게시글 CRUD 작업에 대한 Unit Test와 End-to-end Test를 진행해봅니다.

velog.io

728x90