NestJS는 Jest를 기반으로 테스트 환경을 제공하여, 단위 테스트(Unit Testing)와 통합 테스트(Integration Testing)를 효율적으로 작성할 수 있는 프레임워크를 제공합니다. 또한 CLI를 통해 서비스나 컨트롤러를 생성할 때 자동으로 테스트 파일(spec.ts)을 생성하여, 개발자가 쉽게 테스트를 작성할 수 있도록 지원합니다.
1. NestJS에서 테스트의 중요성
테스트는 애플리케이션의 안정성과 신뢰성을 보장하기 위한 필수 요소입니다. 이를 통해 코드가 의도한 대로 동작하는지, 변경 사항이 발생해도 기존의 기능이 문제가 없는지를 검증할 수 있습니다. 특히, 단위 테스트와 통합 테스트를 적절히 작성하면, 애플리케이션의 버그를 조기에 발견하고 수정할 수 있습니다.
2. 테스트의 유형
2.1. 단위 테스트 (Unit Testing)
- 단위 테스트는 개별 컴포넌트를 독립적으로 테스트하는 방식입니다. 예를 들어, 서비스나 컨트롤러 같은 컴포넌트를 테스트합니다.
- 모의(Mock) 객체를 사용하여 의존성을 제거한 상태로 테스트를 진행할 수 있습니다.
- 각 기능이 의도한 대로 동작하는지 확인하는 것이 목적입니다.
2.2. 통합 테스트 (Integration Testing)
- 통합 테스트는 여러 컴포넌트가 함께 동작하는지 확인하는 테스트입니다. 이는 실제 애플리케이션의 흐름을 최대한 시뮬레이션하는 방식으로 수행됩니다.
- 예를 들어, 서비스와 데이터베이스가 제대로 연결되어 상호작용하는지 확인하는 데 사용됩니다.
- 통합 테스트는 주로 End-to-End (E2E) 테스트와 함께 사용됩니다.
3. NestJS에서 테스트 파일 자동 생성
NestJS CLI를 사용하면 컨트롤러나 서비스를 생성할 때 테스트 파일도 함께 자동으로 생성됩니다. 이는 기본적인 테스트 구조를 제공하며, 테스트 작성에 필요한 틀을 마련해줍니다.
3.1. 서비스 생성 시 자동으로 생성되는 spec.ts
nest generate service users
이 명령을 실행하면 users.service.ts 파일과 함께 users.service.spec.ts 파일이 생성됩니다. 이 테스트 파일에는 UsersService에 대한 기본적인 테스트 템플릿이 포함됩니다.
3.2. 컨트롤러 생성 시 자동으로 생성되는 spec.ts
nest generate controller users
이 명령을 실행하면 users.controller.ts와 함께 users.controller.spec.ts 파일이 생성됩니다. UsersController를 테스트하기 위한 기본 템플릿이 제공됩니다.
4. spec.ts 파일의 기본 구조
자동으로 생성되는 spec.ts 파일은 기본적인 테스트 구조를 제공하며, 여기에 추가적인 테스트 로직을 작성할 수 있습니다.
서비스의 기본 테스트 파일 템플릿:
import { Test, TestingModule } from '@nestjs/testing';
import { UsersService } from './users.service';
describe('UsersService', () => {
let service: UsersService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [UsersService],
}).compile();
service = module.get<UsersService>(UsersService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});
컨트롤러의 기본 테스트 파일 템플릿:
import { Test, TestingModule } from '@nestjs/testing';
import { UsersController } from './users.controller';
describe('UsersController', () => {
let controller: UsersController;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [UsersController],
}).compile();
controller = module.get<UsersController>(UsersController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
});
5. 테스트 작성 방법
자동으로 생성된 spec.ts 파일을 기반으로 테스트를 작성할 수 있습니다. 여기서는 단위 테스트와 통합 테스트를 어떻게 작성할 수 있는지 간단한 예시를 통해 설명합니다.
5.1. 단위 테스트 예시 (UsersService)
it('should return all users', () => {
const result = service.findAll();
expect(result).toBeInstanceOf(Array);
});
- findAll() 메서드가 배열을 반환하는지 확인하는 테스트입니다.
- NestJS의 TestModule을 사용하여 서비스의 인스턴스를 주입받아 테스트를 진행합니다.
5.2. 컨트롤러 테스트 예시 (UsersController)
it('should return an array of users', async () => {
const result = await controller.findAll();
expect(result).toEqual(['user1', 'user2']);
});
- UsersService의 findAll() 메서드를 모의(Mock) 처리하여 컨트롤러가 의도한 대로 동작하는지 확인합니다.
- jest.fn()을 사용해 모의된 데이터를 반환하고, 그 데이터를 기반으로 컨트롤러의 동작을 테스트합니다.
6. 통합 테스트 (E2E 테스트)
통합 테스트는 실제 서버와 상호작용하여 전체 애플리케이션이 예상대로 동작하는지를 검증합니다. supertest 라이브러리를 사용해 실제 HTTP 요청을 시뮬레이션하고, 결과를 테스트합니다.
통합 테스트 예시 (UsersController)
import * as request from 'supertest';
it('/users (GET)', () => {
return request(app.getHttpServer())
.get('/users')
.expect(200)
.expect([{ id: 1, name: 'John Doe' }]);
});
- request(app.getHttpServer()): 실제 서버에 요청을 보내고, 응답을 검증합니다.
- E2E 테스트는 실제 API 엔드포인트가 예상대로 동작하는지 확인하는 데 유용합니다.
7. 테스트 실행 방법
NestJS는 Jest를 기본으로 통합하여 쉽게 테스트를 실행할 수 있는 명령어를 제공합니다.
- npm run test: 모든 테스트 실행.
- npm run test:watch: 파일이 변경될 때마다 테스트 자동 실행.
- npm run test:e2e: End-to-End 테스트 실행.
- npm run test:cov: 테스트 커버리지를 계산하고 출력.
8. Mocking과 의존성 주입
NestJS는 의존성 주입을 사용하여 테스트 환경에서 모의(Mock) 객체를 쉽게 사용할 수 있습니다. 이를 통해 실제 데이터베이스나 외부 서비스에 의존하지 않고, 컴포넌트의 기능만을 테스트할 수 있습니다.
{
provide: UsersService,
useValue: {
findAll: jest.fn().mockResolvedValue(['user1', 'user2']),
},
}
이렇게 설정하면 UsersService의 findAll 메서드는 실제 데이터베이스에 접근하지 않고, 모의 데이터를 반환하게 됩니다.
'Category > NestJs' 카테고리의 다른 글
| NestJs에 Swagger 적용하는 법 (0) | 2025.04.23 |
|---|---|
| NestJS에서 DTO는 왜 클래스(class)로 작성해야 할까? (0) | 2025.04.08 |
| NestJS에서의 테스트 작성 예시 (1) | 2024.10.30 |