728x90
반응형
예시: 사용자 관리 시스템
1. 사용자 서비스 (UsersService) 단위 테스트
서비스는 주로 비즈니스 로직을 담당하는 컴포넌트입니다. 여기서는 사용자 정보를 관리하는 UsersService의 단위 테스트를 작성해보겠습니다.
UsersService 코드
import { Injectable } from '@nestjs/common';
@Injectable()
export class UsersService {
private users = [{ id: 1, name: 'John Doe', email: 'john@example.com' }];
findAll() {
return this.users;
}
findOne(id: number) {
return this.users.find(user => user.id === id);
}
create(user) {
this.users.push(user);
return user;
}
}
단위 테스트 작성
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 return all users', () => {
const users = service.findAll();
expect(users).toEqual([{ id: 1, name: 'John Doe', email: 'john@example.com' }]);
});
it('should return a single user by id', () => {
const user = service.findOne(1);
expect(user).toEqual({ id: 1, name: 'John Doe', email: 'john@example.com' });
});
it('should create a new user', () => {
const newUser = { id: 2, name: 'Jane Doe', email: 'jane@example.com' };
const createdUser = service.create(newUser);
expect(createdUser).toEqual(newUser);
expect(service.findAll()).toContainEqual(newUser);
});
});
설명:
- findAll, findOne, create 메서드를 테스트합니다.
- expect를 사용하여 반환된 데이터가 예상한 결과와 일치하는지 확인합니다.
- 각 테스트는 해당 서비스 메서드가 잘 동작하는지, 특히 새로운 사용자를 추가하거나 조회하는 기능이 올바르게 작동하는지를 검증합니다.
2. 사용자 컨트롤러 (UsersController) 단위 테스트
컨트롤러는 사용자 요청을 처리하는 부분으로, 여기서는 HTTP 요청을 처리하는 UsersController를 단위 테스트합니다. 컨트롤러는 주로 서비스에 의존하므로, 서비스를 모의(mock)로 처리하여 테스트합니다.
UsersController 코드
import { Controller, Get, Param, Post, Body } from '@nestjs/common';
import { UsersService } from './users.service';
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Get()
findAll() {
return this.usersService.findAll();
}
@Get(':id')
findOne(@Param('id') id: string) {
return this.usersService.findOne(Number(id));
}
@Post()
create(@Body() user) {
return this.usersService.create(user);
}
}
단위 테스트 작성
import { Test, TestingModule } from '@nestjs/testing';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
describe('UsersController', () => {
let controller: UsersController;
let service: UsersService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [UsersController],
providers: [
{
provide: UsersService,
useValue: {
findAll: jest.fn().mockResolvedValue([{ id: 1, name: 'John Doe', email: 'john@example.com' }]),
findOne: jest.fn().mockResolvedValue({ id: 1, name: 'John Doe', email: 'john@example.com' }),
create: jest.fn().mockResolvedValue({ id: 2, name: 'Jane Doe', email: 'jane@example.com' }),
},
},
],
}).compile();
controller = module.get<UsersController>(UsersController);
service = module.get<UsersService>(UsersService);
});
it('should return an array of users', async () => {
const users = await controller.findAll();
expect(users).toEqual([{ id: 1, name: 'John Doe', email: 'john@example.com' }]);
});
it('should return a single user by id', async () => {
const user = await controller.findOne('1');
expect(user).toEqual({ id: 1, name: 'John Doe', email: 'john@example.com' });
});
it('should create a new user', async () => {
const newUser = { name: 'Jane Doe', email: 'jane@example.com' };
const createdUser = await controller.create(newUser);
expect(createdUser).toEqual({ id: 2, name: 'Jane Doe', email: 'jane@example.com' });
});
});
설명:
- jest.fn().mockResolvedValue(): UsersService의 메서드들을 모의(mock)로 처리하여 가짜 값을 반환합니다.
- 컨트롤러의 각 메서드가 잘 동작하는지를 테스트합니다. 실제 데이터베이스와 상호작용하지 않고, 서비스에서 제공되는 모의 데이터만으로 테스트를 진행합니다.
3. 통합 테스트 (E2E 테스트)
E2E 테스트는 실제 HTTP 요청을 통해 서버와 상호작용하며, 여러 컴포넌트가 잘 통합되어 동작하는지 확인하는 방식입니다.
E2E 테스트 작성
import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import * as request from 'supertest';
import { AppModule } from './../src/app.module';
describe('UsersController (e2e)', () => {
let app: INestApplication;
beforeAll(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleFixture.createNestApplication();
await app.init();
});
it('/users (GET)', () => {
return request(app.getHttpServer())
.get('/users')
.expect(200)
.expect([{ id: 1, name: 'John Doe', email: 'john@example.com' }]);
});
it('/users/:id (GET)', () => {
return request(app.getHttpServer())
.get('/users/1')
.expect(200)
.expect({ id: 1, name: 'John Doe', email: 'john@example.com' });
});
it('/users (POST)', () => {
return request(app.getHttpServer())
.post('/users')
.send({ name: 'Jane Doe', email: 'jane@example.com' })
.expect(201)
.expect({ id: 2, name: 'Jane Doe', email: 'jane@example.com' });
});
afterAll(async () => {
await app.close();
});
});
설명:
- supertest 라이브러리를 사용하여 실제 HTTP 요청을 시뮬레이션합니다.
- 서버가 실제로 잘 동작하는지, /users 경로로 GET, POST 요청을 보내 결과를 검증합니다.
- E2E 테스트는 통합적인 테스트로서, 실제 요청과 응답을 기반으로 하여 애플리케이션이 예상대로 작동하는지 확인합니다.
4. 테스트 실행
테스트를 실행하는 방법은 간단합니다. NestJS 프로젝트에서 기본적으로 제공하는 명령어를 사용하면 됩니다.
- npm run test: 모든 테스트 실행
- npm run test:watch: 파일이 변경될 때마다 테스트 자동 실행
- npm run test:e2e: E2E 테스트 실행
- npm run test:cov: 테스트 커버리지 확인
요약:
이 예시에서는 사용자 관리 시스템을 기반으로 단위 테스트와 E2E 테스트를 작성하는 방법을 설명했습니다.
- 단위 테스트는 각 서비스나 컨트롤러가 제대로 동작하는지를 독립적으로 확인하며, 모의(mock) 객체를 사용해 외부 의존성을 제거합니다.
- E2E 테스트는 실제 서버와 HTTP 요청을 통해 애플리케이션이 예상대로 동작하는지 확인합니다.
NestJS는 Jest와 supertest를 기본으로 지원하여 테스트 환경을 쉽게 설정하고, 각 컴포넌트를 개별적으로 또는 통합적으로 테스트할 수 있는 도구를 제공합니다.
'Category > NestJs' 카테고리의 다른 글
| NestJs에 Swagger 적용하는 법 (0) | 2025.04.23 |
|---|---|
| NestJS에서 DTO는 왜 클래스(class)로 작성해야 할까? (0) | 2025.04.08 |
| NestJS에서의 테스트: 기본 개념부터 실제 사용까지 (0) | 2024.10.30 |