使用请求对 NestJS 控制器进行单元测试
Posted
技术标签:
【中文标题】使用请求对 NestJS 控制器进行单元测试【英文标题】:Unit testing NestJS controller with request 【发布时间】:2018-12-27 13:37:07 【问题描述】:我的 Controller 函数定义如下所示:
async login(@Req() request, @Body() loginDto: LoginDto): Promise<any>
如何准备/模拟请求以提供来自 Jest 测试的函数的第一个参数?
在函数内部,我使用request.res.set
设置标题。我应该以某种方式将真实的 Request 对象传递给函数,然后检查是否设置了标头,还是模拟整个 Request 对象并检查是否调用了 set 函数?
【问题讨论】:
【参考方案1】:我设法使用 node-mocks-http
库来模拟请求和响应。
const req = mocks.createRequest()
req.res = mocks.createResponse()
然后将其作为参数传递。
const data = await authController.login(req, loginDto)
expect(req.res.get('AccessToken')).toBe(token.accessToken)
【讨论】:
在 NestJS 中这是一种好的(惯用的)方法吗,因为它应该负责通过注入解决所有依赖项?我只是问,因为我也在寻找一种方法来实现它。 这不再有效,类型已更改并且 createRequest() 的返回类型与控制器需要的不兼容。 现在该怎么做?【参考方案2】:我采用了不同的方法,我没有使用node-mocks-http
库,而是使用@golevelup/ts-jest,也没有测试函数是否返回一些值,比如res.json()
或res.status()
,我检查了函数是否被调用具有我想要的价值。
我从好老Kent C. Dodds's testing workshop那里借用了这种方法,看看类似的想法。无论如何,这就是我为了mock
我的Controller's route
的Response
依赖所做的:
// cars.controller.spec.ts
import createMock from '@golevelup/ts-jest';
const mockResponseObject = () =>
return createMock<Response>(
json: jest.fn().mockReturnThis(),
status: jest.fn().mockReturnThis(),
);
;
... ommited for brevity
it('should return an array of Cars', async () =>
const response = mockResponseObject();
jest
.spyOn(carsService, 'findAll')
.mockImplementation(jest.fn().mockResolvedValueOnce(mockedCarsList));
await carsController.getCars(response);
expect(response.json).toHaveBeenCalledTimes(1);
expect(response.json).toHaveBeenCalledWith( cars: mockedCarsList );
expect(response.status).toHaveBeenCalledTimes(1);
expect(response.status).toHaveBeenCalledWith(200);
);
就是这样,我认为实现细节并不那么重要,但无论如何我会将链接留给Github repo,在那里你可以找到整个项目。
【讨论】:
@golevelup/ts-jest
是为此类问题创建的
供参考:@golevelup/ts-jest以上是关于使用请求对 NestJS 控制器进行单元测试的主要内容,如果未能解决你的问题,请参考以下文章
在 NestJS 中使用 Jest 和 MongoDB 进行单元测试