728x90
반응형

서비스 로직이 안정적으로 동작하는지를 검증하기 위해
단위 테스트(Unit Test)는 필수적이다.
본 글에서는 실제 프로젝트에서 개발한 MeasurementRuleService에 대해
테스트 코드 생성부터 구성, 실행 방식까지 상세히 정리한다.
📦 테스트 대상 서비스 개요
MeasurementRuleService는 치수 규칙(MeasurementRule)을 생성하는 유스케이스 로직을 담당하며,
다음과 같은 검증을 포함한다:
- 규칙 이름 중복 검사
- 동일 조합(category + 소매 + 넥라인) 중복 검사
- 규칙 저장 후 확인
SQLite 기반 in-memory DB로 통합 테스트 진행
본 테스트는 실제 PostgreSQL과 연결하지 않고,
테스트 전용 in-memory DB인 SQLite를 활용하여
MeasurementRuleService의 규칙 생성 흐름을 검증한다.
테스트 시점에 메모리에서 테이블을 구성하고 테스트가 끝나면 자동 삭제되므로,
Spring의 H2DB 테스트 방식과 유사하게 빠른 속도로 테스트를 반복할 수 있다.
sqlite 설치 :
npm install sqlite3 --save📄 테스트 코드
// src/application/measurement-rule/measurement-rule.service.int.spec.ts
import { Test, TestingModule } from '@nestjs/testing';
import { TypeOrmModule } from '@nestjs/typeorm';
import { MeasurementRuleService } from './measurement-rule.service';
import { MeasurementRule } from 'src/domain/mesurement-rule/measurement-rule.entity';
import { MeasurementRuleItem } from 'src/domain/mesurement-rule/Measurement-rule-item.entity';
describe('MeasurementRuleService (통합 테스트 - SQLite)', () => {
let service: MeasurementRuleService;
beforeAll(async () => {
const module: TestingModule = await Test.createTestingModule({
imports: [
TypeOrmModule.forRoot({
type: 'sqlite',
database: ':memory:',
dropSchema: true,
entities: [MeasurementRule, MeasurementRuleItem],
synchronize: true,
logging: false,
}),
TypeOrmModule.forFeature([MeasurementRule, MeasurementRuleItem]),
],
providers: [MeasurementRuleService],
}).compile();
service = module.get<MeasurementRuleService>(MeasurementRuleService);
});
describe('createRule()', () => {
const dto = {
ruleName: '테스트_규칙',
categorySmall: '스웨터',
sleeveType: '레글런',
neckLineType: '라운드넥',
};
it('새로운 규칙을 정상적으로 생성할 수 있어야 한다', async () => {
const result = await service.createRule(dto);
expect(result).toBeDefined();
expect(result.ruleName).toBe(dto.ruleName);
expect(result.categorySmall).toBe(dto.categorySmall);
expect(result.sleeveType).toBe(dto.sleeveType);
});
it('같은 이름의 규칙이 존재할 경우 예외가 발생해야 한다', async () => {
await service.createRule({
ruleName: '중복규칙',
categorySmall: '스웨터',
});
await expect(
service.createRule({
ruleName: '중복규칙',
categorySmall: '스웨터',
}),
).rejects.toThrow('중복된 규칙 이름입니다.');
});
it('같은 조합(categorySmall + sleeveType + neckLineType)이 존재할 경우 예외가 발생해야 한다', async () => {
const input = {
ruleName: '조합검증용',
categorySmall: '가디건',
sleeveType: '라글란',
neckLineType: '브이넥',
};
await service.createRule(input);
await expect(service.createRule({
ruleName: '다른이름이지만조합중복',
categorySmall: '가디건',
sleeveType: '라글란',
neckLineType: '브이넥',
})).rejects.toThrow('해당 조합의 규칙이 이미 존재합니다.');
});
});
});✅ 정리
- SQLite in-memory 모드(
:memory:) 를 사용하면 실제 DB 설치 없이 빠르고 독립적인 테스트 환경을 구성할 수 있다. dropSchema: true+synchronize: true설정을 통해 테스트 실행 시마다 새로 스키마를 구성한다.- 테스트 코드와 실제 서비스 코드 간의 간극이 없기 때문에, Mock보다 더 신뢰도 높은 테스트가 가능하다.
📦 참고 설정 요약
| 항목 | 설정 |
|---|---|
| DB 종류 | sqlite |
| DB 파일 경로 | :memory: → 메모리 상의 임시 DB |
synchronize |
true → 테이블 자동 생성 |
dropSchema |
true → 테스트마다 DB 리셋 |
logging |
false → 로그 출력 생략 |
728x90
반응형
'Nest.js' 카테고리의 다른 글
| Nest.js 개발에 필요한 주요 CLI 명령어와 활용법 (1) | 2025.05.22 |
|---|---|
| Nest CLI란 무엇인가? (0) | 2025.05.22 |
| Nest.js에서의 직렬화와 역직렬화 (0) | 2025.05.22 |
| [Nest.js] 애플리케이션 진입점 (0) | 2025.05.22 |
| [Nest.js] 프로젝트 구조 설계 (0) | 2025.05.22 |