我可以肯定地说,在 sinon 或 sinon-chai 中不存在这样的东西。
这是测试任何未使用结果的基于 Promise 的函数所固有的困难。如果使用结果,您知道必须先解决承诺,然后再继续处理所述结果。如果不是这样,事情就会变得更加复杂,并且超出了 sinon 可以通过简单的存根为您做的事情的范围。
一种天真的方法是使用一个假动作来存根该动作,该假动作设置一些变量(对于您的测试来说是本地的)来跟踪状态。像这样:
let actionComplete = false;
const actionStub = sinon.stub(someAction).callsFake(() => {
return new Promise((resolve) => {
setImmediate(() => {
actionComplete = true;
resolve();
});
});
});
expect(actionStub).to.have.been.calledWith();
expect(actionComplete).to.be.true;
当然,这里的问题是等待 any 承诺,不一定是这个特定的承诺,将通过这个测试,因为变量将在事件循环的下一步被设置,不管是什么让你等待下一步。
例如,您可以在被测代码中使用类似这样的内容来通过:
someAction();
await new Promise((resolve) => {
setImmediate(() => resolve());
});
更稳健的方法是创建两个单独的测试。一个是 promise 解决的地方,一个是 promise 拒绝的地方。您可以测试以确保拒绝会导致包含函数以相同的错误拒绝,如果该特定承诺不是awaited,则这是不可能的。
const actionStub = sinon.stub(someAction).resolves();
// In one test
expect(actionStub).to.have.been.calledWith();
// In another test
const actionError = new Error('omg bad error');
actionStub.rejects(actionError);
// Assuming your test framework supports returning promises from tests.
return functionUnderTest()
.then(() => {
throw new Error('Promise should have rejected');
}, (err) => {
expect(err).to.equal(actionError);
});
一些断言库和扩展(可能是 chai-as-promised)可能有一种方法可以清除那里使用的脱糖承诺。我不想对你使用的工具做太多假设,只是想确保这个想法得到传达。