[英]Unit testing NestJS controller with injection
I need to make an unit test for a controller who use injection with NestJS.我需要对使用 NestJS 注入的 controller 进行单元测试。
I don't know how to mock and spy this service (MyEmitter).我不知道如何模拟和监视此服务(MyEmitter)。 I need to declare it in test.controller.spec.ts inside beforeEach() but how?我需要在 beforeEach() 内的 test.controller.spec.ts 中声明它,但是如何?
test.controller.ts测试.controller.ts
import {
Controller,
Body,
Post,
} from '@nestjs/common';
import {
WebhookDto,
} from './dto/webhook.dto';
import { MyEmitter } from './test.events';
import { InjectEventEmitter } from 'nest-emitter';
@Controller()
export class TestController {
constructor(
@InjectEventEmitter() private readonly myEmitter: MyEmitter,
) {}
@Post('webhook')
public async postWebhook(
@Body() webhookDto: WebhookDto,
): Promise<void> {
...
this.myEmitter.emit('webhook', webhookDto);
}
}
test.controller.spec.ts test.controller.spec.ts
import { Test, TestingModule } from '@nestjs/testing';
import { TestController } from './test.controller';
import EventEmitter = require('events');
import { EVENT_EMITTER_TOKEN } from 'nest-emitter';
import { MyEmitter } from './test.events';
describe('Test Controller', () => {
let testController: TestController;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
imports: [],
providers: [
{
provide: EVENT_EMITTER_TOKEN,
useValue: {
emit: jest.fn(),
},
},
],
controllers: [TestController],
}).compile();
testController = module.get<TestController>(TetsController);
});
describe('postWebhook', () => {
it('should send the event', async () => {
const myEmitterSpy = jest.spyOn(myEmitter, 'emit');
const result = await testController.postWebhook({...});
expect(myEmitterSpy).toBeCalledTimes(1);
});
});
});
Thank you really much for your help.非常感谢您的帮助。
The easiest way to go about it, with the setup you currently have is to use module.get()
like you already are for the controller and pass in the EVENT_EMITTER_TOKEN
constant, then save that to a value declared in the describe
block, just like how the let testController: TestController
works. go 关于它的最简单方法,您当前拥有的设置是使用module.get()
就像您已经用于 controller 并传入EVENT_EMITTER_TOKEN
常量,然后将其保存到describe
块中声明的值,就像let testController: TestController
是如何工作的。 Something like this should suffice:像这样的东西就足够了:
import { Test, TestingModule } from '@nestjs/testing';
import { TestController } from './test.controller';
import EventEmitter = require('events');
import { EVENT_EMITTER_TOKEN } from 'nest-emitter';
import { MyEmitter } from './test.events';
describe('Test Controller', () => {
let testController: TestController;
let myEmitter: MyEmitter;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
imports: [],
providers: [
{
provide: EVENT_EMITTER_TOKEN,
useValue: {
emit: jest.fn(),
},
},
],
controllers: [TestController],
}).compile();
testController = module.get<TestController>(TetsController);
myEmitter = module.get<MyEmitter>(EVENT_EMITTER_TOKEN);
});
describe('postWebhook', () => {
it('should send the event', async () => {
const myEmitterSpy = jest.spyOn(myEmitter, 'emit'); // you can also add on mockResponse type functions here like mockReturnValue and mockResolvedValue
const result = await testController.postWebhook({...});
expect(myEmitterSpy).toBeCalledTimes(1);
});
});
});
Rather than injecting every dependencies (which should be tested separately), it is better to use jest.spyOn because controller has a service dependency or dependencies which might have other dependencies.与其注入每个依赖项(应单独测试),不如使用 jest.spyOn 更好,因为 controller 具有服务依赖项或可能具有其他依赖项的依赖项。
We should mock the method that will be called in the current test.我们应该模拟将在当前测试中调用的方法。
Here is the sample controller test.这是样品 controller 测试。
import { SampleController } from './sample.controller';
import { SampleService } from './sample.service';
describe('SampleController', () => {
let sampleController: SampleController;
let sampleService: SampleService;
beforeEach(() => {
// SampleService depends on a repository class
// Passing null becasue SampleService will be mocked
// So it does not need any dependencies.
sampleService = new SampleService(null);
// SampleController has one dependency SampleService
sampleController = new SampleController(sampleService);
});
it('should be defined', async () => {
expect(sampleController).toBeDefined();
});
describe('findAll', () => {
it('should return array of samples', async () => {
// Response of findAllByQuery Method
// findAllByQUeryParams is a method of SampleService class.
// I want the method to return an array containing 'test' value'.
const expectedResult = ['test'];
// Creating the mock method
// The method structure is the same as the actual method structure.
const findAllByQueryParamsMock = async (query: any) => expectedResult;
// I am telling jest to spy on the findAllByQueryParams method
// and run the mock method when the findAllByQueryParams method is called in the controller.
jest
.spyOn(sampleService, 'findAllByQueryParams')
.mockImplementation(findAllByQueryParamsMock);
const actualResult = await sampleController.findAll({});
expect(actualResult).toBe(expectedResult);
});
});
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.