这是我用Typescript为Nodejs / Nestjs编写的BadRequestExceptionFilter
@Catch(BadRequestException)
export class BadRequestExceptionFilter implements ExceptionFilter {
constructor(private logger: AppLoggerService) {}
catch(exception: BadRequestException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse();
const request = ctx.getRequest();
const status =
exception instanceof BadRequestException
? exception.getStatus()
: HttpStatus.INTERNAL_SERVER_ERROR;
const message = {
Title: exception.message.error,
Type: 'Exception - BadRequestExceptionFilter',
Detail: exception.message,
Status: '',
};
this.logger.error(message, '');
response.code(status).send({
statusCode: status,
...(exception.getResponse() as object),
timestamp: 'Exception - BadRequestException' + new Date().toISOString(),
});
}
}
这是我的单元测试,这里有2个断言。 第一个断言是检查是否调用了mockLogger.error。这是工作。 第二个断言,用于检查是否调用response.code(status).send()。 但出现此错误。 Expect(jest.fn())。toBeCalled()
Expected number of calls: >= 1
Received number of calls: 0
const mockLogger = { error: jest.fn() };
const mockContext: any = {
switchToHttp: () => ({
getRequest: () => ({
url: 'mock-url',
}),
getResponse: () => {
const response = {
code: jest.fn().mockReturnThis(),
send: jest.fn().mockReturnThis(),
};
return response;
},
}),
};
describe('BadRequestExceptionFilter', () => {
let filter: BadRequestExceptionFilter;
beforeEach(() => {
filter = new BadRequestExceptionFilter(mockLogger as any);
});
it('should catch and log the error', () => {
const mockException: BadRequestException = new BadRequestException();
mockException.name = 'BadRequestException';
mockException.getResponse = jest.fn().mockReturnValue(of('getResponse'));
mockException.getStatus = () => 404;
jest.fn(mockContext.switchToHttp().getResponse().send);
filter.catch(mockException, mockContext);
expect(mockLogger.error).toBeCalled();
expect(
mockContext
.switchToHttp()
.getResponse()
.code().send,
).toBeCalled();
});
});
答案 0 :(得分:3)
我认为使用Nest Testing模块为异常过滤器编写测试用例很简单。请在下面查看我如何达到同样的效果:
// all-exception.filter.spec.ts
import {
Test,
TestingModule
} from '@nestjs/testing';
import {
HttpStatus,
HttpException
} from '@nestjs/common';
import { AllExceptionsFilter } from './all-exceptions.filter';
import { AppLoggerService } from '../services/logger/app-logger.service';
const mockAppLoggerService = {
info: jest.fn(),
error: jest.fn(),
warn: jest.fn(),
debug: jest.fn()
};
const mockJson = jest.fn();
const mockStatus = jest.fn().mockImplementation(() => ({
json: mockJson
}));
const mockGetResponse = jest.fn().mockImplementation(() => ({
status: mockStatus
}));
const mockHttpArgumentsHost = jest.fn().mockImplementation(() => ({
getResponse: mockGetResponse,
getRequest: jest.fn()
}));
const mockArgumentsHost = {
switchToHttp: mockHttpArgumentsHost,
getArgByIndex: jest.fn(),
getArgs: jest.fn(),
getType: jest.fn(),
switchToRpc: jest.fn(),
switchToWs: jest.fn()
};
describe('System header validation service', () => {
let service: AllExceptionsFilter;
beforeEach(async () => {
jest.clearAllMocks();
const module: TestingModule = await Test.createTestingModule({
providers: [
AllExceptionsFilter,
{
provide: AppLoggerService,
useValue: mockAppLoggerService
},
]
}).compile();
service = module.get<AllExceptionsFilter>(AllExceptionsFilter);
});
describe('All exception filter tests', () => {
it('should be defined', () => {
expect(service).toBeDefined();
});
it('Http exception', () => {
service.catch(
new HttpException('Http exception', HttpStatus.BAD_REQUEST),
mockArgumentsHost
);
expect(mockHttpArgumentsHost).toBeCalledTimes(1);
expect(mockHttpArgumentsHost).toBeCalledWith();
expect(mockGetResponse).toBeCalledTimes(1);
expect(mockGetResponse).toBeCalledWith();
expect(mockStatus).toBeCalledTimes(1);
expect(mockStatus).toBeCalledWith(HttpStatus.BAD_REQUEST);
expect(mockJson).toBeCalledTimes(1);
expect(mockJson).toBeCalledWith({
message: 'Http exception'
});
});
});
});
答案 1 :(得分:0)
在过滤器中,您有...(expection.getResponse() as object)
,但exception
上没有功能getResponse()
。相反,您需要先切换到http上下文
答案 2 :(得分:0)
我做了这样的事情,它奏效了!
export const contextMock = (roles?: string[]) => {
const ctx: any = {}
ctx.switchToHttp = jest.fn().mockReturnValue({
getRequest: jest.fn().mockReturnValue(requestMock()),
getResponse: jest.fn().mockReturnValue(responseMock()),
})
ctx.getHandler = jest.fn().mockReturnValue({ roles }) as Function
return ctx
}
-----------------------------------------------
const ctxMock = contextMock() as any
expect(ctxMock.switchToHttp).toHaveBeenCalled()
expect(ctxMock.switchToHttp().getResponse).toHaveBeenCalled()
expect(ctxMock.switchToHttp().getResponse().status).toHaveBeenCalled()
expect(ctxMock.switchToHttp().getResponse().json).toHaveBeenCalled()
据我了解,我们总是必须为“期望”传递一个模拟。