ํ‹ฐ์Šคํ† ๋ฆฌ ๋ทฐ

๋ฐ˜์‘ํ˜•

๐Ÿงช NestJS Testing – ์œ ๋‹› ํ…Œ์ŠคํŠธ๋ถ€ํ„ฐ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๊นŒ์ง€ ์™„์ „ ์ •๋ณต


NestJS๋Š” ํ…Œ์ŠคํŠธ๋ฅผ ํ”„๋ ˆ์ž„์›Œํฌ ์ˆ˜์ค€์—์„œ ๊ฐ•๋ ฅํ•˜๊ฒŒ ์ง€์›ํ•˜๋Š” ๊ตฌ์กฐ๋ฅผ ๊ฐ–๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
์ด๋ฒˆ ๊ธ€์€ NestJS ๊ณต์‹ ๋ฌธ์„œ Testing์„ ๋ฐ”ํƒ•์œผ๋กœ,
์œ ๋‹› ํ…Œ์ŠคํŠธ(Unit Test), ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ(Integration Test), ๊ทธ๋ฆฌ๊ณ  E2E ํ…Œ์ŠคํŠธ๋ฅผ ์‹ค๋ฌด ์ค‘์‹ฌ์œผ๋กœ ๊ตฌ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ’ก “ํ…Œ์ŠคํŠธ๋Š” ์„ ํƒ์ด ์•„๋‹Œ ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค. NestJS๋Š” DI์™€ ๋ชจ๋“ˆ ์‹œ์Šคํ…œ ๋•๋ถ„์— ํ…Œ์ŠคํŠธ ์ž‘์„ฑ์ด ๋งค์šฐ ์‰ฝ์Šต๋‹ˆ๋‹ค.”


โœ… ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ ์ค€๋น„

NestJS๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ Jest๋ฅผ ํ…Œ์ŠคํŠธ ๋Ÿฌ๋„ˆ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

โœ… ์„ค์ • ํŒŒ์ผ

NestJS ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ ์‹œ ์ž๋™ ํฌํ•จ:

- jest.config.ts
- test/jest-e2e.json

โœ… ์„ค์น˜ ํ™•์ธ

npm run test           # ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ์‹คํ–‰
npm run test:watch     # ๋ณ€๊ฒฝ ๊ฐ์ง€ ๋ชจ๋“œ
npm run test:cov       # ์ปค๋ฒ„๋ฆฌ์ง€ ํฌํ•จ ์‹คํ–‰
npm run test:e2e       # E2E ํ…Œ์ŠคํŠธ ์‹คํ–‰

1๏ธโƒฃ ์œ ๋‹› ํ…Œ์ŠคํŠธ (Unit Test)

โœ… ์„œ๋น„์Šค ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ์˜ˆ์‹œ

// cats.service.ts
@Injectable()
export class CatsService {
  getCats() {
    return ['๊ณ ์–‘์ด1', '๊ณ ์–‘์ด2'];
  }
}
// cats.service.spec.ts
describe('CatsService', () => {
  let service: CatsService;

  beforeEach(() => {
    service = new CatsService();
  });

  it('should return an array of cats', () => {
    expect(service.getCats()).toEqual(['๊ณ ์–‘์ด1', '๊ณ ์–‘์ด2']);
  });
});

๐Ÿงช ์˜์กด์„ฑ์ด ์—†๋Š” ์„œ๋น„์Šค๋Š” new ์—ฐ์‚ฐ์ž๋กœ ๋ฐ”๋กœ ์ƒ์„ฑํ•˜์—ฌ ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅ


๐Ÿ“บ ๊ด‘๊ณ 

์ด ๊ตฌ๊ฐ„์€ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๊ฐ€ ์‹ค์ œ ์‹คํ–‰๋˜๋Š” ์˜ˆ์ œ๊ฐ€ ๋“ฑ์žฅํ•˜๋Š” ๊ตฌ๊ฐ„์œผ๋กœ
์• ๋“œ์„ผ์Šค ๊ด‘๊ณ  ์‚ฝ์ž…์— ์ ํ•ฉํ•œ ๊ณ ์ฃผ๋ชฉ ์˜์—ญ์ž…๋‹ˆ๋‹ค.

<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-XXXXXX"
     data-ad-slot="YYYYYY"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>

2๏ธโƒฃ ์˜์กด์„ฑ ์ฃผ์ž…์ด ์žˆ๋Š” ์œ ๋‹› ํ…Œ์ŠคํŠธ

๋ฐ˜์‘ํ˜•

โœ… DI๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ TestingModule ์‚ฌ์šฉ

// cats.service.ts
@Injectable()
export class CatsService {
  constructor(private readonly httpService: HttpService) {}

  async fetchCats(): Promise<string[]> {
    const res = await this.httpService.get('https://api.example.com/cats').toPromise();
    return res.data;
  }
}
</string[]>

โœ… ํ…Œ์ŠคํŠธ ์„ค์ •

describe('CatsService (with DI)', () => {
  let service: CatsService;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        CatsService,
        {
          provide: HttpService,
          useValue: {
            get: jest.fn().mockReturnValue({
              toPromise: () => Promise.resolve({ data: ['cat1', 'cat2'] }),
            }),
          },
        },
      ],
    }).compile();

    service = module.get<CatsService>(CatsService);
  });

  it('should fetch cats', async () => {
    expect(await service.fetchCats()).toEqual(['cat1', 'cat2']);
  });
});

โœ… Test.createTestingModule()์„ ์‚ฌ์šฉํ•˜๋ฉด NestJS์˜ DI ์‹œ์Šคํ…œ์„ ํ…Œ์ŠคํŠธ์—์„œ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


3๏ธโƒฃ ์ปจํŠธ๋กค๋Ÿฌ + ์„œ๋น„์Šค ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ

// cats.controller.ts
@Controller('cats')
export class CatsController {
  constructor(private readonly catsService: CatsService) {}

  @Get()
  getCats() {
    return this.catsService.getCats();
  }
}

โœ… ํ…Œ์ŠคํŠธ ์„ค์ •

describe('CatsController', () => {
  let controller: CatsController;

  beforeEach(async () => {
    const module = await Test.createTestingModule({
      controllers: [CatsController],
      providers: [
        {
          provide: CatsService,
          useValue: {
            getCats: jest.fn().mockReturnValue(['ํ…Œ์ŠคํŠธ ๊ณ ์–‘์ด']),
          },
        },
      ],
    }).compile();

    controller = module.get<CatsController>(CatsController);
  });

  it('should return cats', () => {
    expect(controller.getCats()).toEqual(['ํ…Œ์ŠคํŠธ ๊ณ ์–‘์ด']);
  });
});

4๏ธโƒฃ E2E ํ…Œ์ŠคํŠธ (End-to-End)

NestJS๋Š” E2E ํ…Œ์ŠคํŠธ๋ฅผ supertest์™€ ํ•จ๊ป˜ ๊ธฐ๋ณธ ์ œ๊ณตํ•˜๋ฉฐ test/app.e2e-spec.ts์— ๊ธฐ๋ณธ ํ…œํ”Œ๋ฆฟ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

โœ… ์˜ˆ์‹œ

import * as request from 'supertest';
import { Test } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import { AppModule } from '../src/app.module';

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

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

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

  it('/cats (GET)', () => {
    return request(app.getHttpServer())
      .get('/cats')
      .expect(200)
      .expect(['๊ณ ์–‘์ด1', '๊ณ ์–‘์ด2']);
  });
});

๐Ÿง  ์‹ค๋ฌด ์ „๋žต

ํ…Œ์ŠคํŠธ ์œ ํ˜• ๋ชฉ์  ๋„๊ตฌ

Unit Test ๋‹จ์ผ ํ•จ์ˆ˜, ์„œ๋น„์Šค ๋กœ์ง ๊ฒ€์ฆ Jest
Integration ์—ฌ๋Ÿฌ ๋ชจ๋“ˆ, DI ํฌํ•จ ์„œ๋น„์Šค ํ…Œ์ŠคํŠธ Jest + Test.createTestingModule()
E2E Test ์‹ค์ œ HTTP ์š”์ฒญ ๊ธฐ๋ฐ˜ ์ „์ฒด ํ๋ฆ„ ํ…Œ์ŠคํŠธ Jest + Supertest

๐Ÿ”ง ํ…Œ์ŠคํŠธ ์‹คํ–‰ ๋ช…๋ น ์š”์•ฝ

๋ช…๋ น์–ด ์„ค๋ช…

npm run test ์œ ๋‹› ํ…Œ์ŠคํŠธ ์ˆ˜ํ–‰
npm run test:cov ์ปค๋ฒ„๋ฆฌ์ง€ ๋ฆฌํฌํŠธ ํฌํ•จ ํ…Œ์ŠคํŠธ ์‹คํ–‰
npm run test:e2e E2E ํ…Œ์ŠคํŠธ ์ˆ˜ํ–‰
npm run test:watch ํŒŒ์ผ ๋ณ€๊ฒฝ ์‹œ ์ž๋™ ํ…Œ์ŠคํŠธ

โœ… ๋งˆ๋ฌด๋ฆฌ ์š”์•ฝ

๊ฐœ๋… ์„ค๋ช…

Test.createTestingModule() DI ํ™˜๊ฒฝ์„ ํ…Œ์ŠคํŠธ์—์„œ ๊ตฌ์„ฑํ•˜๋Š” ํ•ต์‹ฌ ๋„๊ตฌ
Mock Provider ์„œ๋น„์Šค ํ…Œ์ŠคํŠธ์—์„œ ์˜์กด์„ฑ ์ฃผ์ž… ๋Œ€์ฒด
E2E ํ…Œ์ŠคํŠธ ์‹ค์ œ ์š”์ฒญ-์‘๋‹ต ํ๋ฆ„์„ ๊ฒ€์ฆํ•˜์—ฌ ์ „์ฒด ์‹œ์Šคํ…œ ํ…Œ์ŠคํŠธ ์ˆ˜ํ–‰
์ปค๋ฒ„๋ฆฌ์ง€ ์ฒดํฌ --coverage ํ”Œ๋ž˜๊ทธ๋กœ ์ปค๋ฒ„๋ฆฌ์ง€ ๋ฆฌํฌํŠธ ์ƒ์„ฑ ๊ฐ€๋Šฅ

 

NestJS ํ…Œ์ŠคํŠธ,NestJS Unit Test,NestJS Integration Test,NestJS E2E Test,NestJS Jest ์„ค์ •,NestJS Mocking,NestJS Test.createTestingModule,NestJS ํ…Œ์ŠคํŠธ ์ฝ”๋“œ,NestJS ํ…Œ์ŠคํŠธ ์‹ค๋ฌด,NestJS Coverage ๋ณด๊ณ ์„œ


 

โ€ป ์ด ํฌ์ŠคํŒ…์€ ์ฟ ํŒก ํŒŒํŠธ๋„ˆ์Šค ํ™œ๋™์˜ ์ผํ™˜์œผ๋กœ, ์ด์— ๋”ฐ๋ฅธ ์ผ์ •์•ก์˜ ์ˆ˜์ˆ˜๋ฃŒ๋ฅผ ์ œ๊ณต๋ฐ›์Šต๋‹ˆ๋‹ค.
๊ณต์ง€์‚ฌํ•ญ
์ตœ๊ทผ์— ์˜ฌ๋ผ์˜จ ๊ธ€
์ตœ๊ทผ์— ๋‹ฌ๋ฆฐ ๋Œ“๊ธ€
Total
Today
Yesterday
๋งํฌ
ยซ   2025/07   ยป
์ผ ์›” ํ™” ์ˆ˜ ๋ชฉ ๊ธˆ ํ† 
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
๊ธ€ ๋ณด๊ด€ํ•จ
๋ฐ˜์‘ํ˜•