当我运行测试“应该调用getDetails()”时,它失败,并显示一条消息,指出该函数被调用0次。如果我记录了间谍,我可以看到它的道具“被叫”等于假。我知道它正在被调用,因为我在console.log
中有一个getDetails
,并且每次调用getMultipleRecords()
时都会显示它。第一个测试工作正常,但是findAll()
是一个承诺,所以我知道这是一个异步问题。
我认为问题在于摩卡咖啡不尊重await
。任何人的反馈意见将不胜感激。
测试:
describe('getMultipleRecords()', () => {
let next = () => {};
let req = { body: { records: [1, 2, 3] } };
let res = {};
// Passing
it('Should call VMBilling.findAll()', async function() {
var findAll = sinon.spy(VMBilling, 'findAll');
await recordCtrl.getMultipleRecords(req, res, next);
//console.log(find)
sinon.assert.calledOnce(findAll);
});
// Failing
it('Should call getDetails()', async function() {
var gd = sinon.spy(recordCtrl, 'getDetails');
await recordCtrl.getMultipleRecords(req, res, next);
sinon.assert.calledOnce(gd);
});
});
我正在测试的功能
const getMultipleRecords = async (req, res, next) => {
try {
console.log('getMultipleRecords()');
let records = await VMBilling.findAll({
include: [
{
model: ErrorMessage,
},
],
where: [
{
id: req.body.records,
},
],
});
let recordsWithDetails = getDetails(records);
console.log(recordsWithDetails);
return res.status(200).json(recordsWithDetails);
} catch (error) {
next(error);
}
}
因为编译后,函数将使用不同的签名,全名导出,并且在存根时我们对全局函数进行存根,但是在其他函数中调用全局函数时,我们调用了本地函数,因此它不起作用。有一种解决方法可以做到这一点。
这里是单元测试解决方案:
controller.ts
import { VMBilling } from './model';
const getDetails = records => {
console.log(records);
};
const getMultipleRecords = async (req, res, next) => {
try {
console.log('getMultipleRecords()');
let records = await VMBilling.findAll({
include: [
{
model: 'ErrorMessage'
}
],
where: [
{
id: req.body.records
}
]
});
let recordsWithDetails = exports.getDetails(records);
console.log(recordsWithDetails);
return res.status(200).json(recordsWithDetails);
} catch (error) {
next(error);
}
};
exports.getMultipleRecords = getMultipleRecords;
exports.getDetails = getDetails;
model.ts
:
export const VMBilling = {
findAll(conditions) {
console.log('conditions');
}
};
controller.spec.ts
:
import { VMBilling } from './model';
import sinon from 'sinon';
const recordCtrl = require('./controller');
describe('getMultipleRecords()', () => {
let next = () => {};
let req = { body: { records: [1, 2, 3] } };
let res = {};
afterEach(() => {
sinon.restore();
});
it('Should call VMBilling.findAll()', async function() {
var findAll = sinon.spy(VMBilling, 'findAll');
await recordCtrl.getMultipleRecords(req, res, next);
sinon.assert.calledOnce(findAll);
});
it('Should call getDetails()', async function() {
var gd = sinon.spy(recordCtrl, 'getDetails');
await recordCtrl.getMultipleRecords(req, res, next);
sinon.assert.calledOnce(gd);
});
});
单元测试结果覆盖率100%:
getMultipleRecords()
getMultipleRecords()
conditions
undefined
undefined
✓ Should call VMBilling.findAll()
getMultipleRecords()
conditions
undefined
undefined
✓ Should call getDetails()
2 passing (9ms)
--------------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
--------------------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
controller.spec.ts | 100 | 100 | 100 | 100 | |
controller.ts | 100 | 100 | 100 | 100 | |
model.ts | 100 | 100 | 100 | 100 | |
--------------------|----------|----------|----------|----------|-------------------|
源代码:https://github.com/mrdulin/mocha-chai-sinon-codelab/tree/master/src/stackoverflow/58209098