Mocking은 단위 테스트를 작성할 때
해당 코드가 의존하는 부분을 가짜(mock)으로 대체하는 기법
테스트하려는 코드가 의존하는 부분을 직접 생성하기 부담스러운 경우 mocking 을 사용
Mocking은 실제 객체인 척하는 가짜 객체를 생성하는 매커니즘을 제공
테스트가 실행되는 동안 Mocking 객체가 호출되거나,
어떤 아웃풋을 반환하는지 등을 기억하기에 어떻게 사용되는지 검증이 가능
Mocking을 이용하면 구체적으로 구현해야 하는 실제 객체 사용보다 훨씬 빠르고,
동일한 결과를 내는 테스트를 작성 가능
NestJS는 Dependency Injection을 통해 각 Module을 캡슐화하여
서로 의존성을 최대한 배제하고 주입하여 사용하는 특징이 있음
NestJS의 Test환경을 조성할 경우 의존성을 주입하지 않고 의존성 자체를 Mocking해야 함
unit Test를 하기 위해 실제 코드가 실행되는 환경과 같은 환경을 조성
import { Test, TestingModule } from '@nestjs/testing';
import { AppController } from './app.controller';
import { AppService } from './app.service';
class MockAppService {
getHello() {
return 'Hello World!';
}
}
describe('AppController', () => {
let appController: AppController;
beforeEach(async () => {
const app: TestingModule = await Test.createTestingModule({
controllers: [AppController],
providers: [
{
provide: AppService,
useClass: MockAppService,
},
],
}).compile();
appController = app.get<AppController>(AppController);
});
describe('getHello', () => {
it('return Hello World!', () => {
expect(appController.getHello()).toBe('Hello World!');
});
});
});
import { ConflictException } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import { getRepositoryToken } from '@nestjs/typeorm';
import { UserService } from '../user.service';
import { User } from '../entities/user.entity';
class MockUserRepository {
mydb = [{ email: 'a@a.com', password: '0000', mobileNumber: '01011111111' }];
findOne({ email }) {
const users = this.mydb.filter((el) => el.email === email);
if (users.length) return users[0];
return null;
}
save({ email, password, mobileNumber }) {
this.mydb.push({ email, password, mobileNumber });
return { email, password, mobileNumber };
}
}
describe('UserService', () => {
let userService: UserService;
beforeEach(async () => {
const userModule: TestingModule = await Test.createTestingModule({
providers: [
UserService,
{
provide: getRepositoryToken(User),
useClass: MockUserRepository,
},
],
}).compile();
userService = userModule.get<UserService>(UserService);
});
describe('create', () => {
it('이미 존재하는 이메일 검증하기!!', async () => {
const myData = {
email: 'a@a.com',
password: '1234',
mobileNumber: '01011111111',
};
try {
await userService.create({ ...myData });
} catch (error) {
expect(error).toBeInstanceOf(ConflictException);
}
});
it('회원 등록 검증', async () => {
const myData = {
email: 'bbb@bbb.com',
password: '1234',
mobileNumber: '01011111111',
};
const myResultData = {
email: 'bbb@bbb.com',
password: '1234',
mobileNumber: '01011111111',
};
const result = await userService.create({ ...myData });
expect(result).toStrictEqual(myResultData);
});
});
});
TestingModule을 생성할 때 UserRepository를 mocking
it에 mock 값을 넣어서 create할 때 올바른 값을 반환하는지 확인하는 테스트 코드 작성