0

我在运行测试(在节点中)时遇到问题,

我正在模拟一个被拒绝的承诺,我的代码应该重试(如果可能相关,请使用promise-retry )。

当我使用模拟被拒绝的承诺时stub.returns(Promise.reject(error)

我收到了一个未捕获的错误警告(对于我的dummyErrors),即使我在调用我的函数时发现了错误......

-注意,这些未捕获的错误仅发生在单元测试中,而不是实际调用中。

const mockedFunction = sinon.stub();

const dummyError = new Error('Document is locked');

mockedFunction.onCall(0).returns(Promise.reject(dummyError));
mockedFunction.onCall(0).returns(Promise.reject(dummyError));
mockedFunction.onCall(0).returns(Promise.reject(dummyError));
mockedFunction.onCall(1).returns(Promise.resolve({approved: true}));

我发现通过更改使用stub.rejects()语法:

mockedFunction.onCall(0).rejects(dummyError);
mockedFunction.onCall(1).rejects(dummyError);
mockedFunction.onCall(2).rejects(dummyError));
mockedFunction.onCall(3).resolves({approved: true});

我不再收到未捕获的错误警告。

我的问题解决了,但是我想更好地理解为什么,我查看了 sinon 源代码,看起来实现.rejects没有什么不同

4

1 回答 1

3

在本质上检测未捕获错误的 Promise 实现中(包括 V8/Node.js),来自被拒绝的 Promise 的错误应该在同一滴答声中被捕获,否则它会触发UnhandledPromiseRejectionWarning.

这将正常工作:

let promise = Promise.reject();
promise.catch(() => {});

这将导致潜在的未处理承诺并触发警告:

let promise = Promise.reject();
setTimeout(() => {
  promise.catch(() => {});
});

如果Promise.reject(dummyError)没有与同一个刻度链接catch(...)then(..., ...)在同一个刻度上,它会触发一个警告,而如果rejects(dummyError)在函数调用上创建一个被拒绝的承诺,那么这很可能是真的:

sinon.spy(Promise, 'reject');
mockedFunction.onCall(0).rejects(dummyError);
expect(Promise.reject).to.have.not.been.called;
mockedFunction();
expect(Promise.reject).to.have.been.called;

一种替代方法rejects(dummyError)是:

mockedFunction.onCall(0).callsFake(() => Promise.reject(dummyError))
于 2018-06-13T18:01:11.813 回答