Testing
Testing
์๋ ํ ์คํธ๋ ๋ชจ๋ ๊ธฐ๋ฅ์ ๊ฐ์ถ ์ํํธ์จ์ด ์ ํ์ ํ์ ๋ถ๋ถ์ ๋๋ค. ์์คํ ์ ๊ฐ์ฅ ๋ฏผ๊ฐํ ๋ถ๋ถ์ ๋ค๋ฃจ๋ ๊ฒ์ด ๋งค์ฐ ์ค์ํฉ๋๋ค. ์ด๋ฌํ ๋ชฉํ๋ฅผ ๋ฌ์ฑํ๊ธฐ ์ํด ํตํฉ ํ ์คํธ, ๋จ์ ํ ์คํธ, e2e ํ ์คํธ ๋ฑ๊ณผ ๊ฐ์ ๋ค์ํ ํ ์คํธ ์ธํธ๋ฅผ ์์ฑํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ Nest๋ ํ ์คํธ ๊ฒฝํ์ ํฅ์์ํค๋ ๋ค์ํ ํ ์คํธ ์ ํธ๋ฆฌํฐ๋ฅผ ์ ๊ณตํฉ๋๋ค.
์ผ๋ฐ์ ์ผ๋ก, ๋น์ ์ ํ ์คํ ํ๋ ์ ์ํฌ๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ํด๋ง์ ์ํํ์ง ์์ผ๋ฉฐ ์๊ตฌ ์ฌํญ์ ๋ง๋ ๊ฒ์ ์ ํํ์ญ์์ค. ๊ธฐ๋ณธ Nest ์ ํ๋ฆฌ์ผ์ด์  ์คํํฐ๋ Jest ํ๋ ์ ์ํฌ์ ํตํฉ๋์ด ํ ์คํธ ์์ฑ์ ์์ํ ๋ ๋ฐ์ํ๋ ์ค๋ฒ ํค๋๋ฅผ ์ค์ด์ง๋ง ์ฌ์ ํ ์ ๊ฑฐํ ์ ์์ต๋๋ค. ๋ค๋ฅธ ๋๊ตฌ๋ฅผ ์ฝ๊ฒ ์ฌ์ฉํ์ญ์์ค.
Installation
๋จผ์  ํ์ํ ํจํค์ง๋ฅผ ์ค์นํด์ผํฉ๋๋ค.
$ npm i --save-dev @nestjs/testingUnit testing
๋ค์ ์์ ์์๋ ๊ฐ๊ฐ CatsController์ CatsService๋ผ๋ ๋ ๊ฐ์ง ํด๋์ค๊ฐ ์์ต๋๋ค. ์์์ ์ธ๊ธํ๋ฏ์ด Jest๋ ๋ณธ๊ฒฉ์ ์ธ ํ
์คํธ ํ๋ ์ ์ํฌ๋ก ์ฌ์ฉ๋ฉ๋๋ค. ์ด ํ๋ ์ ์ํฌ๋ ํ
์คํธ ์คํ๊ธฐ์ฒ๋ผ ์๋ํ๋ฉฐ, ๋ชจ์, ๊ฐ์ ๋ฑ์ ๋๋ assert ํจ์ ๋ฐ test-doubles ์ ํธ๋ฆฌํฐ๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ผ๋จ ํธ์ถ ๋ result๋ณ์๋ฅผ ๋ฐํํ๋๋กcatsService.findAll()๋ฉ์๋๋ฅผ ์๋์ผ๋ก ์ ์ฉํ์ต๋๋ค. ๋๋ถ์ catsController.findAll()์ด ์์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋์ง ํ
์คํธํ  ์ ์์ต๋๋ค.
@@filename(cats.controller.spec)
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';
describe('CatsController', () => {
  let catsController: CatsController;
  let catsService: CatsService;
  beforeEach(() => {
    catsService = new CatsService();
    catsController = new CatsController(catsService);
  });
  describe('findAll', () => {
    it('should return an array of cats', async () => {
      const result = ['test'];
      jest.spyOn(catsService, 'findAll').mockImplementation(() => result);
      expect(await catsController.findAll()).toBe(result);
    });
  });
});
@@switch
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';
describe('CatsController', () => {
  let catsController;
  let catsService;
  beforeEach(() => {
    catsService = new CatsService();
    catsController = new CatsController(catsService);
  });
  describe('findAll', () => {
    it('should return an array of cats', async () => {
      const result = ['test'];
      jest.spyOn(catsService, 'findAll').mockImplementation(() => result);
      expect(await catsController.findAll()).toBe(result);
    });
  });
});info ํํธ ํ ์คํธ ํ์ผ์ ํ ์คํธ๋ ํด๋์ค ๊ทผ์ฒ์ ๋ณด๊ดํ์ญ์์ค. ํ ์คํธ ํ์ผ์๋
.spec๋๋.test์ ๋ฏธ์ฌ๊ฐ ์์ด์ผํฉ๋๋ค.
์ฐ๋ฆฌ๋ ์ง๊ธ๊น์ง ๊ธฐ์กด Nest ํ ์คํธ ์ ํธ๋ฆฌํฐ๋ฅผ ์ฌ์ฉํ์ง ์์์ต๋๋ค. ํ ์คํธ ํ ํด๋์ค์ ์ธ์คํด์คํ๋ฅผ ์๋์ผ๋ก ์ฒ๋ฆฌ ํ์ผ๋ฏ๋ก ์์ ํ ์คํธ ์ค์ํธ๋ Nest์ ๊ด๋ จ์ด ์์ต๋๋ค. ์ด๋ฌํ ์ ํ์ ํ ์คํธ๋ฅผ isolated ํ ์คํธ๋ผ๊ณ ํฉ๋๋ค.
Testing utilities
@nestjs/testing ํจํค์ง๋ ํ
์คํธ ํ๋ก์ธ์ค๋ฅผ ํฅ์์ํค๋ ์ ํธ๋ฆฌํฐ ์ธํธ๋ฅผ ์ ๊ณตํฉ๋๋ค. ๋
ธ์ถ ๋Test ํด๋์ค๋ฅผ ์ฌ์ฉํ์ฌ ์ด์  ์์ ๋ฅผ ๋ค์ ์์ฑํด ๋ด
์๋ค.
@@filename(cats.controller.spec)
import { Test } from '@nestjs/testing';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';
describe('CatsController', () => {
  let catsController: CatsController;
  let catsService: CatsService;
  beforeEach(async () => {
    const module = await Test.createTestingModule({
        controllers: [CatsController],
        providers: [CatsService],
      }).compile();
    catsService = module.get<CatsService>(CatsService);
    catsController = module.get<CatsController>(CatsController);
  });
  describe('findAll', () => {
    it('should return an array of cats', async () => {
      const result = ['test'];
      jest.spyOn(catsService, 'findAll').mockImplementation(() => result);
      expect(await catsController.findAll()).toBe(result);
    });
  });
});
@@switch
import { Test } from '@nestjs/testing';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';
describe('CatsController', () => {
  let catsController;
  let catsService;
  beforeEach(async () => {
    const module = await Test.createTestingModule({
        controllers: [CatsController],
        providers: [CatsService],
      }).compile();
    catsService = module.get(CatsService);
    catsController = module.get(CatsController);
  });
  describe('findAll', () => {
    it('should return an array of cats', async () => {
      const result = ['test'];
      jest.spyOn(catsService, 'findAll').mockImplementation(() => result);
      expect(await catsController.findAll()).toBe(result);
    });
  });
});Test ํด๋์ค์๋ ๋ชจ๋ ๋ฉํ ๋ฐ์ดํฐ ( @Module) ๋ฐ์ฝ๋ ์ดํฐ์ ์ ๋ฌ๋ ๊ฒ๊ณผ ๋์ผํ ๊ฐ์ฒด)๋ฅผ ์ธ์๋ก ์ทจํ๋createTestingModule()๋ฉ์๋๊ฐ ์์ต๋๋ค. ์ด ๋ฉ์๋๋ TestingModule ์ธ์คํด์ค๋ฅผ ๋ง๋ค์ด ๋ช ๊ฐ์ ๋ฉ์๋๋ฅผ ์ ๊ณตํ์ง๋ง ๋จ์ ํ
์คํธ์ ๊ด๋ จํ์ฌ ์ปดํ์ผ ์ค ํ๋ ์ธ compile()๋ง ์ ์ฉํฉ๋๋ค. ์ด ๊ธฐ๋ฅ์ ๋น๋๊ธฐ์ด๋ฏ๋ก ๊ธฐ๋ค๋ ค์ผํฉ๋๋ค. ๋ชจ๋์ด ์ปดํ์ผ๋๋ฉด, get() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๋ชจ๋  ์ธ์คํด์ค๋ฅผ ๊ฒ์ ํ  ์ ์์ต๋๋ค.
์ค์  ์ธ์คํด์ค๋ฅผ ๋ชจ๋ฐฉํ๊ธฐ ์ํด custom provider๋ก ๊ธฐ์กด ๊ณต๊ธ์๋ฅผ ์ฌ์ ์ ํ ์ ์์ต๋๋ค.
End-to-end testing
์ ํ๋ฆฌ์ผ์ด์ ์ด ์ปค์ง๋ฉด ๊ฐ API ์๋ ํฌ์ธํธ์ ๋์์ ์๋์ผ๋ก ํ ์คํธํ๊ธฐ๊ฐ ์ด๋ ต์ต๋๋ค. ์๋ ํฌ ์๋ ํ ์คํธ๋ ๋ชจ๋ ๊ฒ์ด ์ฌ๋ฐ๋ฅด๊ฒ ์๋ํ๊ณ ํ๋ก์ ํธ ์๊ตฌ ์ฌํญ์ ๋ง๋์ง ํ์ธํ๋ ๋ฐ ๋์์ด๋ฉ๋๋ค. e2e ํ ์คํธ๋ฅผ ์ํํ๊ธฐ ์ํด unit testing์ ๊ฒฝ์ฐ์ ๋์ผํ ๊ตฌ์ฑ์ ์ฌ์ฉํ์ง๋ง HTTP ์์ฒญ์ ์๋ฎฌ๋ ์ด์  ํ ์์๋ supertest ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํ์ฉํฉ๋๋ค. .
@@filename(cats.e2e-spec)
import * as request from 'supertest';
import { Test } from '@nestjs/testing';
import { CatsModule } from '../../src/cats/cats.module';
import { CatsService } from '../../src/cats/cats.service';
import { INestApplication } from '@nestjs/common';
describe('Cats', () => {
  let app: INestApplication;
  let catsService = { findAll: () => ['test'] };
  beforeAll(async () => {
    const module = await Test.createTestingModule({
      imports: [CatsModule],
    })
      .overrideProvider(CatsService)
      .useValue(catsService)
      .compile();
    app = module.createNestApplication();
    await app.init();
  });
  it(`/GET cats`, () => {
    return request(app.getHttpServer())
      .get('/cats')
      .expect(200)
      .expect({
        data: catsService.findAll(),
      });
  });
  afterAll(async () => {
    await app.close();
  });
});
@@switch
import * as request from 'supertest';
import { Test } from '@nestjs/testing';
import { CatsModule } from '../../src/cats/cats.module';
import { CatsService } from '../../src/cats/cats.service';
import { INestApplication } from '@nestjs/common';
describe('Cats', () => {
  let app: INestApplication;
  let catsService = { findAll: () => ['test'] };
  beforeAll(async () => {
    const module = await Test.createTestingModule({
      imports: [CatsModule],
    })
      .overrideProvider(CatsService)
      .useValue(catsService)
      .compile();
    app = module.createNestApplication();
    await app.init();
  });
  it(`/GET cats`, () => {
    return request(app.getHttpServer())
      .get('/cats')
      .expect(200)
      .expect({
        data: catsService.findAll(),
      });
  });
  afterAll(async () => {
    await app.close();
  });
});info ํํธ e2e ํ ์คํธ ํ์ผ์
e2e๋๋ ํ ๋ฆฌ ์์ ๋ณด๊ดํ์ญ์์ค. ํ ์คํธ ํ์ผ์๋.e2e-spec๋๋.e2e-test์ ๋ฏธ์ฌ๊ฐ ์์ด์ผํฉ๋๋ค.
cats.e2e-spec.ts ํ
์คํธ ํ์ผ์ ๋จ์ผ HTTP ์๋ ํฌ์ธํธ ํ
์คํธ (/cats)๋ฅผ ํฌํจํฉ๋๋ค. ์ฐ๋ฆฌ๋app.getHttpServer()๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ Nest ์ ํ๋ฆฌ์ผ์ด์
์ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์คํ๋๋ ๊ธฐ๋ณธ HTTP ์๋ฒ๋ฅผ ์ ํํ์ต๋๋ค. TestingModule ์ธ์คํด์ค๋ overrideProvider()๋ฉ์๋๋ฅผ ์ ๊ณตํ๋ฏ๋ก ๊ฐ์ ธ์จ ๋ชจ๋์ ์ํด ์ ์ธ ๋ ๊ธฐ์กด ์ ๊ณต์๋ฅผ ์ค๋ฒ๋ผ์ด๋ ํ  ์ ์์ต๋๋ค. ๋ํ ํด๋น ๋ฉ์๋ ์ธ overrideGuard(), overrideInterceptor (), overrideFilter()๋ฐ overridePipe()๋ฅผ ๊ฐ๊ฐ ์ฌ์ฉํ์ฌ ๊ฐ๋, ์ธํฐ์
ํฐ, ํํฐ ๋ฐ ํ์ดํ๋ฅผ ์ฐ์์ ์ผ๋ก ๋์ฒด ํ  ์ ์์ต๋๋ค.
์ปดํ์ผ๋ ๋ชจ๋์๋ ๋ค์ ํ์ ์ ์ค๋ช ๋ ์ฌ๋ฌ ๊ฐ์ง ๋ฐฉ๋ฒ์ด ์์ต๋๋ค.
 createNestApplicaton()
 ์ฃผ์ด์ง ๋ชจ๋์ ๊ธฐ๋ฐ์ผ๋ก Nest ์ธ์คํด์ค๋ฅผ ๋ง๋ญ๋๋ค (INestApplication ๋ฐํ). init() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ ํ๋ฆฌ์ผ์ด์
์ ์๋์ผ๋ก ์ด๊ธฐํํด์ผ ํฉ๋๋ค.
 createNestMicroservice()
 ์ง์ ๋ ๋ชจ๋์ ๊ธฐ๋ฐ์ผ๋ก Nest ๋ง์ดํฌ๋ก ์๋น์ค ์ธ์คํด์ค๋ฅผ ๋ง๋ญ๋๋ค (INestMicroservice๋ฅผ ๋ฐํ ํจ).
 get()
์ ํ๋ฆฌ์ผ์ด์  ์ปจํ ์คํธ์์ ์ฌ์ฉ ๊ฐ๋ฅํ ์ปจํธ๋กค๋ฌ ๋๋ ์ ๊ณต์ (๊ฐ๋, ํํฐ ๋ฑ ํฌํจ)์ ์ธ์คํด์ค๋ฅผ ๊ฒ์ํฉ๋๋ค.
 select()
 ์๋ฅผ ๋ค์ด, ๋ชจ๋ ๊ทธ๋ํ๋ฅผ ํ์ํ์ฌ ์ ํํ ๋ชจ๋์์ ํน์  ์ธ์คํด์ค๋ฅผ ๊ฐ์ ธ์ต๋๋ค (get() ๋ฉ์๋์์ ํ์ฑํ ๋ ์๊ฒฉ ๋ชจ๋strict:true์ ํจ๊ป ์ฌ์ฉ).
Last updated
Was this helpful?