Node, Nest, Deno/🦁 Nest - Series

Nest + Jest + supertest e2e test (1) : setting

DarrenKwonDev 2020. 12. 13. 02:56
* 테스트 코드를 작성할 공수가 제한적이라면 E2E만 하세요.
프론트엔드, 백엔드, E2E 모든 영역에서 테스트 코드를 작성 하면 좋겠지만 그 정도의 공수를 투입하는것은 현실적으로 힘든 일입니다. 만약 하나만 골라서 제대로 해야 한다면 저는 E2E만 테스트 코드를 작성 하겠습니다. 종단(EndPoint)에서 테스트를 통과하면 기능이 잘 작동하는 것이고 종단에서 실패하는 테스트가 진짜 문제입니다.
출처 - medium.com/hbsmith/e2e-test-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0-3c524862469d

 

코드를 작성하면서 프로젝트를 진행할 때 다른 건 몰라도 중요 로직은 e2e 테스트를 짜는 것이 좋다는 생각이 들었습니다. 열심해 해 봅시다!

 

Nest에서는 unit test와 e2e test를 미리 세팅해두었습니다. unit test에는 package.json에 세팅되어 있고, e2e test는 test파일에 jest-e2e.json에 정의되어 있습니다.

 

jest 세팅 사항들은 unit test와 같습니다. 기본 설정에서 mouduleNameMapper만 설정해주었습니다.

darrengwon.tistory.com/998?category=915252

{
  "moduleFileExtensions": ["js", "json", "ts"],
  "rootDir": ".",
  "testEnvironment": "node",
  "testRegex": ".e2e-spec.ts$",
  "transform": {
    "^.+\\.(t|j)s$": "ts-jest"
  },
  "moduleNameMapper": {
    "^src/(.*)$": "<rootDir>/../src/$1"
  }
}

 

E2E 테스트에서 주의할 점은, 테스트 환경를 독립시켜야 한다는 것입니다. 사용하는 환경 변수도 .env.test에 따로 저장했고, DB도 테스트 DB를 사용해야 합니다.

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      envFilePath: process.env.NODE_ENV === 'dev' ? '.env.dev' : '.env.test', // 개발 환경
      ... (중략)

 

e2e 테스트를 위한 코드의 기반입니다.

테스트가 끝나면 DB를 drop해야 합니다. 그렇지 않으면 다음 테스트에 영향을 미칠 수 있기 때무입니다.

그 다음으로는 app.close()를 통해 앱을 닫아야합니다.

import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import request from 'supertest';
import { AppModule } from '../src/app.module';
import { getConnection } from 'typeorm';

describe('AppController (e2e)', () => {
  let app: INestApplication;

  beforeAll(async () => {
    const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    app = moduleFixture.createNestApplication();
    await app.init();
  });

  afterAll(async () => {
    // e2e 테스트가 끝나면 db를 drop해야 함
    await getConnection().dropDatabase();
    app.close();
  });

  it.todo('createAccount');
  it.todo('userProfile');
  it.todo('login');
  it.todo('me');
  it.todo('verifyEmail');
  it.todo('editProfile');
});

 

그리고 테스트하는 순서도 생각해야 합니다. 실제 DB를 사용하기 때문에 테스트 코드가 다음 테스트에 영향을 미칠 수 있습니다. 따라서 실제 유저가 거쳐가는 비즈니스 로직을 그대로 따라가는 것이 좋습니다.

 

또 DB sync를 하는 것이 좋습니다. 마지막에 dropDatabase를 한 후에 다시 테이블을 생성해야하니깐요.