'Nest : test NestMiddleware, can't trigger event
I use a NestMiddleware for HTTP logging (see http-logging-middleware.ts)
This middleware works fine but when I try to test this NestMiddleware with Jest, I don't know how to trigger the event "close" on the response (see http-logging-middleware.spec.ts)
Any help is welcome :-)
Environnement
$ npm --version
6.14.13
$ node --version
v14.17.0
$ nest --version
8.2.1
http-logging-middleware.ts
import { Injectable, Logger, NestMiddleware } from '@nestjs/common';
import { NextFunction, Request, Response } from 'express';
@Injectable()
export class HttpLoggingMiddleware implements NestMiddleware {
private logger = new Logger(HttpLoggingMiddleware.name, { timestamp: true });
use(request: Request, response: Response, next: NextFunction): void {
const now = Date.now();
const { baseUrl, ip, method } = request;
const userAgent = request.headers['user-agent'] || '';
response.on('close', () => {
const statusCode = response.statusCode;
const contentLength = response['_contentLength'];
const message = {
statusCode: statusCode,
method: method,
path: baseUrl,
contentLength: contentLength,
delay: `${Date.now() - now}`,
ip: ip,
userAgent: userAgent,
};
this.logger.log(message);
});
next();
}
}
http-logging-middleware.spec.ts
import { NextFunction } from 'express';
import { Test } from '@nestjs/testing';
import * as httpMocks from 'node-mocks-http';
import { HttpLoggingMiddleware } from './http-logging-middleware';
describe('HttpLoggingMiddleware', () => {
let httpLoggingMiddleware: HttpLoggingMiddleware;
beforeEach(async () => {
const module = await Test.createTestingModule({
providers: [HttpLoggingMiddleware],
}).compile();
httpLoggingMiddleware = module.get<HttpLoggingMiddleware>(
HttpLoggingMiddleware,
);
});
afterEach(() => {
jest.clearAllMocks();
});
it('should be defined', () => {
expect(httpLoggingMiddleware).toBeDefined();
});
describe('use', () => {
it('should intercept request and log related infos', (done: any) => {
const mockRequest = httpMocks.createRequest();
const mockResponse = httpMocks.createResponse();
const nextFunction: NextFunction = jest.fn(() => {
mockResponse.emit('close');
});
httpLoggingMiddleware.use(mockRequest, mockResponse, nextFunction);
expect(nextFunction).toHaveBeenCalled();
});
});
});
Solution 1:[1]
Thanks to [https://github.com/nestjs/nest/blob/master/integration/hello-world/e2e/middleware.spec.ts][1] (Kamil Mysliwiec) the test works :-)
http-logging-middleware.spec.ts #2
import {
Controller,
Get,
INestApplication,
MiddlewareConsumer,
Module,
} from '@nestjs/common';
import { Test } from '@nestjs/testing';
import { HttpLoggingMiddleware } from './http-logging-middleware';
import { createMock } from '@golevelup/ts-jest';
import * as request from 'supertest';
import { LoggerModule } from '../../logger/logger.module';
import { Logger } from '../../logger/logger.service';
@Controller()
class TestController {
@Get('test')
test() {
return 'test';
}
}
const loggerMock = createMock<Logger>();
@Module({
controllers: [TestController],
imports: [LoggerModule],
providers: [
{
provide: Logger,
useValue: loggerMock,
},
],
})
class TestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(HttpLoggingMiddleware).forRoutes('*');
}
}
describe('HttpLoggingMiddleware', () => {
let app: INestApplication;
beforeEach(async () => {
const module = await Test.createTestingModule({
imports: [TestModule],
providers: [
HttpLoggingMiddleware,
{
provide: Logger,
useValue: loggerMock,
},
],
}).compile();
app = module.createNestApplication();
await app.init();
});
it(`should intercept request and log related infos`, () => {
return request(app.getHttpServer())
.get('/test')
.expect(200, 'test')
.then(() => {
expect(loggerMock.log).toBeCalledTimes(1);
});
});
afterEach(async () => {
await app.close();
});
});```
[1]: https://github.com/nestjs/nest/blob/master/integration/hello-world/e2e/middleware.spec.ts
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Olivier Deslandes |
