如何使用SinonJs来监视没有await的异步调用的数量



在下面的例子中,我有两个函数doTask和doSubTask。两者都是异步的,但由于一些业务需要,我需要解雇& &;忘记两次使用不同参数的doSubTask

const wait = ms => new Promise(resolve => setTimeout(resolve, ms))
const doTask = async (taskId) => {
await wait(taskId)
doSubTask(taskId * 3)
doSubTask(taskId * 5)
console.log('end task :' + taskId)
}
const doSubTask = async (subTaskId) => {
await wait(subTaskId)
console.log('end subTask :' + subTaskId)
}
doTask(2000)

我如何为doTask写一个测试用例,并断言doSubTask已经被调用了两次?


这是一个代码示例,你可以在runkit.com上运行它

require("@fatso83/mini-mocha").install()
const sinon = require("sinon@7.5.0")
const referee = require("@sinonjs/referee")
const chai = require('chai')
chai.use(require('sinon-chai'))
const expect = chai.expect
const wait = ms => new Promise(resolve => setTimeout(resolve, ms))
const doTask = async (taskId) => {
await wait(taskId)
doSubTask(taskId * 3)
doSubTask(taskId * 5)
console.log('end task :' + taskId)
}
const doSubTask = async (subTaskId) => {
await wait(subTaskId)
console.log('end subTask :' + subTaskId)
}
const app = {
doTask,
doSubTask,
}
describe("stub", function () {
it("doSubTask should be called twice", async function () {
const doSubTaskSpy = sinon.spy(app, 'doSubTask')

await doTask(2000)

expect(doSubTaskSpy).to.be.calledTwice()
})
})

上面代码的输出是:

stub
end task :2000
❌ doSubTask should be called twice (Failed with: "expecte…e been called exactly twice, but it was called 0 times")
end subTask :6000
end subTask :10000

我们应该使用rewire包来要求模块和存根doSubTask函数。此外,当promisesetTimeout同时使用时,我们应该使用这种方法来使用假计时器和提前时间。

index.js:

const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const doTask = async (taskId) => {
await wait(taskId);
doSubTask(taskId * 3);
doSubTask(taskId * 5);
console.log('end task :' + taskId);
};
const doSubTask = async (subTaskId) => {
await wait(subTaskId);
console.log('end subTask :' + subTaskId);
};
const app = {
doTask,
doSubTask,
};
module.exports = app;

index.test.js:

const rewire = require('rewire');
const sinon = require('sinon');
describe('stub', function () {
let clock;
before(() => {
clock = sinon.useFakeTimers();
});
after(() => {
clock.restore();
});
it('doSubTask should be called twice', async function () {
const doSubTaskStub = sinon.stub();
const mod = rewire('./');
mod.__set__('doSubTask', doSubTaskStub);
const promise = mod.doTask(2000);
clock.tick(2010);
await promise;
sinon.assert.calledTwice(doSubTaskStub);
sinon.assert.calledWithExactly(doSubTaskStub, 6000);
sinon.assert.calledWithExactly(doSubTaskStub, 10000);
});
});

测试结果:

stub
end task :2000
✓ doSubTask should be called twice (738ms)

1 passing (743ms)
----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |   84.62 |      100 |      75 |   81.82 |                   
index.js |   84.62 |      100 |      75 |   81.82 | 11-12             
----------|---------|----------|---------|---------|-------------------

最新更新