我有一个中间件,如下所示,我正在尝试使用 jest 对其进行单元测试,
中间件:
import Ph from './Ph.model';
fAP = (req, res, next) => {
const pN = req.body.pN;
if (pN != null) {
Ph.aggregate([
{ $match: { 'polNum': { $eq: pN } } },
{
$match: {
$expr:
{
$and: [
{ $eq: ['$pCS', 'A'] }
]
}
}
}
]).exec((err, data) => {
if (data.length > 0) {
req.p = data[0];
req.body.pN = data[0].pN;
return next();
} else {
return res.json({ message: 'Not found'});
}
});
} else {
return res.json({ message: 'Cannot be null.'});
}
}
测试代码:
import { Request, Response, NextFunction } from 'express';
import PhCtrl from 'Ph.controller';
const PhController = new PhCtrl();
import Ph from './Ph.model';
describe('PhController', () => {
let mockRequest: any;
let mockResponse: any;
let mockNext: NextFunction = jest.fn();
beforeEach(() => {
mockRequest = {
body: {
polNum: ''
}
};
mockResponse = {
json: jest.fn()
};
});
// fAP middleware
describe('fAP middleware', () => {
// pN is not null and matches
describe('when pn is not null', () => {
// found
test('should call next when matches', async () => {
const mockRequest: any = {
body: {
pN: '3028'
}
};
const mockResponse: any = {
json: jest.fn()
};
const mockNext: NextFunction = jest.fn();
const responseData = require('../../../mock-data/p.json');
Ph.aggregate = jest.fn().mockImplementationOnce(() => ({
exec: jest.fn().mockResolvedValueOnce(responseData)
}));
await PhController.fAP(
mockRequest,
mockResponse,
mockNext
);
expect(mockNext).toHaveBeenCalled();
});
});
});
});
错误: 但是当我尝试模拟聚合函数时,我收到以下错误。 在 findOne 的情况下,类似的过程有效,但在 mongoose 的聚合方法中失败。任何帮助将不胜感激。
<块引用>● PhController › fAP 中间件 › 当 pn 不为空 › 匹配时应调用 next
expect(jest.fn()).toHaveBeenCalled()
Expected number of calls: >= 1
Received number of calls: 0
54 | mockNext
55 | );
> 56 | expect(mockNext).toHaveBeenCalled();
| ^
57 | });
58 |
59 | // active ph is not found
at tests/server/api/ph/ph.controller.test.ts:56:26
答案 0 :(得分:1)
您可以使用 jest.mock(moduleName, factory, options) 方法模拟 './Ph.model
模块。
使用 mockFn.mockReturnThis() 来模拟方法链调用。
例如
middleware.ts
:
import Ph from './Ph.model';
export const fAP = (req, res, next) => {
const pN = req.body.pN;
if (pN != null) {
Ph.aggregate([
{ $match: { polNum: { $eq: pN } } },
{
$match: {
$expr: {
$and: [{ $eq: ['$pCS', 'A'] }],
},
},
},
]).exec((err, data) => {
if (data.length > 0) {
req.p = data[0];
req.body.pN = data[0].pN;
return next();
} else {
return res.json({ message: 'Not found' });
}
});
} else {
return res.json({ message: 'Cannot be null.' });
}
};
Ph.model.ts
:
import mongoose from 'mongoose';
const schema = new mongoose.Schema();
const Ph = mongoose.model('Ph', schema);
export default Ph;
middleware.test.ts
:
import { NextFunction } from 'express';
import { fAP } from './middleware';
import { mocked } from 'ts-jest/utils';
import Ph from './Ph.model';
jest.mock('./Ph.model', () => {
return {
aggregate: jest.fn().mockReturnThis(),
exec: jest.fn(),
};
});
describe('66434808', () => {
afterAll(() => {
jest.resetAllMocks();
});
it('should call next when matches', () => {
const responseData = [{ pN: '2222' }];
mocked(Ph.aggregate().exec).mockImplementationOnce((callback) => {
callback!(null, responseData);
});
const mockRequest: any = { body: { pN: '3028' } };
const mockResponse: any = { json: jest.fn() };
const mockNext: NextFunction = jest.fn();
fAP(mockRequest, mockResponse, mockNext);
expect(Ph.aggregate).toBeCalledWith([
{ $match: { polNum: { $eq: '3028' } } },
{
$match: {
$expr: {
$and: [{ $eq: ['$pCS', 'A'] }],
},
},
},
]);
expect(Ph.aggregate().exec).toBeCalledWith(expect.any(Function));
expect(mockNext).toBeCalledTimes(1);
});
});
单元测试结果:
PASS examples/66434808/middleware.test.ts
66434808
✓ should call next when matches (4 ms)
---------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
---------------|---------|----------|---------|---------|-------------------
All files | 83.33 | 50 | 100 | 81.82 |
middleware.ts | 83.33 | 50 | 100 | 81.82 | 22-26
---------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 4.362 s
源代码:https://github.com/mrdulin/jest-v26-codelab/tree/main/examples/66434808