자동화된 테스트는 중요한 소프트웨어 개발의 필수적인 부분으로 여겨집니다. 자동화를 통해 테스트를 손쉽고 빠르게 반복 할 수 있습니다.
Jest는 Facebook에서 만들었고 Twitter, Airbnb에서도 테스팅에 사용하고 있다. NestJS에서 내장되어있는 기능이다.
$ npm i --save-dev @nestjs/testing
NestJS에서는 Module, Controller, Service를 생성하면
.spec.ts
파일이 같이 생성된다. 해당 파일에서Jset
Unit testing을 하면 된다.
Jest는 보통 함수의 반환값을 인자로 받는 expect 함수를 제공한다. 이 함수는 받은 인자를 토대로 'expectation' 객체를 반환한다. 많은 테스트가 이 객체에 붙어 있는 'matchers'라고 불리는 메소드들을 호출함으로써 작성된다.
.toThrow
의 경우 다음과 같이 감싸는 함수를 작성해야 테스트가 실패하지 않는다
function compileAndroidCode() {
throw new Error('you are using the wrong JDK');
}
test('compiling android goes as expected', () => {
expect(() => compileAndroidCode()).toThrow();
expect(() => compileAndroidCode()).toThrow(Error);
// 인자로 에러 메시지나 정규표현식을 넣을 수도 있다.
expect(() => compileAndroidCode()).toThrow('you are using the wrong JDK');
expect(() => compileAndroidCode()).toThrow(/JDK/);
});
movies.service.spec.ts
import { NotFoundException } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import { MoviesService } from './movies.service';
describe('MoviesService', () => {
let service: MoviesService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [MoviesService],
}).compile();
service = module.get<MoviesService>(MoviesService);
});
describe('getAll', () => {
//유닛테스트
it('should return an array', () => {
const result = service.getAll();
expect(result).toBeInstanceOf(Array);
});
});
describe('getOne', () => {
//유닛테스트
it('should return a movie', () => {
service.create({
title: 'test Movie',
genres: ['test'],
year: 2000,
});
const moive = service.getOne(1);
expect(moive).toBeDefined();
expect(moive.id).toEqual(1);
});
it('should thorw 404 error', () => {
try {
service.getOne(999);
} catch (e) {
expect(e).toBeInstanceOf(NotFoundException);
expect(e.message).toEqual(`movie with id 999 not found`);
}
});
});
describe('deleteOne', () => {
//유닛테스트
it('delete a moive', () => {
service.create({
title: 'test movie',
genres: ['test'],
year: 2021,
});
const beforeDelete = service.getAll().length;
service.deleteOne(1);
const afterDelete = service.getAll().length;
expect(afterDelete).toBeLessThan(beforeDelete);
// expect(afterDelte.length).toEqual(allMovies.length - 1);
});
it('shoudl return a 404', () => {
try {
service.deleteOne(999);
} catch (e) {
expect(e).toBeInstanceOf(NotFoundException);
}
});
});
describe('create', () => {
it('should create a movie', () => {
const beforeCreate = service.getAll().length;
service.create({
title: 'test moive',
genres: ['testtest'],
year: 2222,
});
const afterCreate = service.getAll().length;
expect(afterCreate).toBeGreaterThan(beforeCreate);
});
});
describe('update', () => {
it('should update a movie', () => {
service.create({
title: 'test moive',
genres: ['testtest'],
year: 2222,
});
service.update(1, { title: 'updated Test' });
const movie = service.getOne(1);
expect(movie.title).toEqual('updated Test');
});
it('should throw a NotFoundException', () => {
try {
service.update(999, {});
} catch (e) {
expect(e).toBeInstanceOf(NotFoundException);
}
});
});
});
NestJS에 내장되어 있어 스크립트를 따로 수정 하지 않아도 된다.
.spec.ts
파일을 모두 실행 해준다
$ npm run test:watch // or
$ npm run test
실행 시 Jest 테스트를 통과 했는지 못했는지 위와 같이 나온다.
$ npm run test:cov
해당 명령으로 내 모듈에서 몇 퍼센트가 테스팅 작성 되었는지 알수 있다.
Application
Unit Test
는 보다 탄력적이고 강력한 소프트웨어를 만들기 위한 첫 번째 단계입니다.
Code Base를 수정(추가)하는 동안 아무것도 깨뜨리지 않았음을 확신 할 수 있기 때문에Unit Test
를 사용하는 것은 리팩토링에 도움이 됩니다.