Testing
End to End test
-
유닛 테스트보다 넓은 범위를 테스트
- 전체 서비스의 복사본이나 인스턴스 생성
- package.json 의 script를 보면
"test:e2e"
가 있음. src 폴더 내의 파일 실행 X - 서버를 끄고 터미널에서
npm run test:e2e
를 입력해보자.
새로운 E2E 테스트 만들기
test 폴더에 auth.e2e-spec.ts 파일을 만들고 app.e2e-spec.ts의 내용을 복사 붙여넣자.
이 후 조금의 수정을 가한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// auth.e2e-spec.ts
import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import * as request from 'supertest';
import { AppModule } from './../src/app.module';
describe('Authentication System', () => {
let app: INestApplication;
beforeEach(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleFixture.createNestApplication();
await app.init();
});
it('handles a signup request', () => { // 알아보기 쉬운 주석
return request(app.getHttpServer())
.post('/auth/signup') // signup 경로
.send({ email: 'asgkege@akl.com', password: 'qownstn' }) // 무작위 body
.expect(201)
.then((res) => { // response id, email로 올 것
const { id, email } = res.body;
expect(id).toBeDefined();
expect(email).toEqual(email);
});
});
});
터미널에서 npm run test:e2e
를 실행하면 문제가 발생한다. 이유를 알아보자.
테스트 오류
테스트 오류 내용을 보면 status 201 created를 예상했지만 500 Internal Server Error 이 발생하였음을 알 수 있다.
좀더 살펴보면 “Cannot set property ‘userId’ of undefined” 라는 문구를 볼 수 있다.
개발 중에는 애플리케이션이 실행되면 각 모듈(Users Module, Reports Module)이 실행되어 App Module이 실행되고 이는 main.ts 파일에서 import 된다. main.ts 내의 bootstrap function이 실행되면 그 이후로는 port:3000을 listening하는 것이 애플리케이션을 실행하는 것이다. 따라서 개발 중에는 main.ts에 의해 애플리케이션이 실행된다. 그리고 main.ts 내의 cookie-session이나 Validation pipe도 실행되는 것이다.
하지만 test중에는 main.ts는 관여되지 않고 E2E 테스트가 App module을 import하여 실행한다. 따라서 cookie-session이나 Validation pipe도 실행되지 않는다. 따라서 session이 없기 때문에 undefined로 처리되어 위 에러 문구가 발생한다.
해결책
새로운 setup-app.ts 파일을 만들어 미들웨어 과정을 호출하는 함수를 정의하는 방법도 있지만 좀더 nest다운 방법은 따로 있다.
현재 main.ts에서 전역으로 설정되어 있는 Validation Pipe와 cookie-session을 App Module에서 정의하면 된다. 테스트 환경에서도 main.ts는 실행되지 않아도 App Module은 사용하기 때문이다. 이 방법을 위해 Validation pipe, cookie-session을 DI 해야한다.
Validation pipe 옮기기
app.module.ts 파일로 가져와보자
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// app.module.ts
import { Module, ValidationPipe } from '@nestjs/common';
import { APP_PIPE } from '@nestjs/core';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'sqlite',
database: 'db.sqlite',
entities: [User, Report],
synchronize: true,
}),
UsersModule,
ReportsModule,
],
controllers: [AppController],
providers: [
AppService,
{
provide: APP_PIPE, // 추가된 코드
useValue: new ValidationPipe({
whitelist: true,
}),
},
],
})
export class AppModule {}
이제 모든 request때 Validationpipe가 실행될 것이다. main.ts에 남은 app.useGlobalPipes는 지워주자.
cookieSession도 가져와서 맨 아래 APpModule에 추가해주자. r기존 Main.ts에선 삭제한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//app.module.ts
import { Module, ValidationPipe, MiddlewareConsumer } from '@nestjs/common';
const cookieSession = require('cookie-session');
export class AppModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(
cookieSession({
keys: ['anything'],
}),
)
.forRoutes('*');
}
}
1
2
3
4
5
6
7
8
9
10
// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
}
bootstrap();
이제 auth.e2e-spec.ts 파일로 가서 signup 관련 부분 email을 새로운 unique한 것으로 바꿔주고 npm run test:e2e
를 실행해보
테스트 2개가 모두 통과하면 성공이다. 이미 등록한 email로 시도하면 오류가 발생한다. 즉 다시 테스트할 때마다 새로운 email 넣어줘야 한다.. 더 나은 테스트를 위해 각 테스트를 독립적으로 실행할 수 있도록 DB를 청소하거나 새로 만들도록 해야한다. 하지만 테스트한다고 DB 다 날리면 기존 서비스의 유저들은 매번 새로 가입해야한다. 따라서 테스트용, 개발용 을 나누는게 최선이다. 이를 위해 환경 변수(environment variables)를 다루긴 너무 어려우니 ConfigService를 이용해보자