不同的摩卡行为 - 异步/同步承诺



我最近遇到了一个奇怪的行为。我有一个包含很多测试的大项目,其中一些是以同步方式编写的,假设 promise 库是没有deferred的库。

但是,在我的机器上准备环境后(Mac OS X,nodeJS 0.12.18 - 我知道:((,测试似乎以不同的 promise 实现运行 - 这次使用带有延迟的异步版本,因此以下测试失败:

// Some generic mocking code here
instance.doSomething(); // This returns a promise
// Immediately after the previous call, we check the results and clean mocks
sinon.assert.called(request.Request);
request.Request.restore();

它像这样重写后开始工作:

return instance.doSomething().then(function() {
sinon.assert.called(request.Request);
request.Request.restore();
});

总而言之,instance.doSomething执行两个请求。

如果同步调用承诺,则request两次调用都会恢复模拟。如果异步调用承诺,则第一次调用成功,但第二次调用失败,因为在此期间存根已恢复(在第二次调用之前(。

我的问题是:

  • 在我的机器和 CI 上,摩卡有可能使用不同的承诺实现吗?
  • 有没有办法强制摩卡兑现承诺?
  • 也许更改后的 Promise 来自代码中的其他地方?

所有这些看起来真的很奇怪,尤其是当代码使用bluebird作为主 Promise 库时......

如果在承诺得到解决之前,无法保证要测试的内容处于正确的测试状态,那么您应该按照第二个代码段中显示的方式编写测试。这是测试依赖于已解决承诺的条件的正确方法。您的初始代码之所以有效,是因为运气。请考虑以下代码:

const assert = require("assert");
const Promise = require("bluebird");
let moo = "initial";
function someFunc() {
return Promise.resolve()
.then(function () {
moo = "modified";
});
}
beforeEach(() => moo = "initial");
it("test one", () => {
someFunc();
assert.equal(moo, "modified");
});
it("test two", () => {
return someFunc().then(() => {
assert.equal(moo, "modified");
});
});

someFunc的承诺会立即解决,但没关系。test one失败了,因为我没有等待承诺。我使用Bluebird还是Node的股票Promise实现并不重要。

在某些情况下,test one可能会过去,但这只是运气,因为承诺并不能保证它会起作用。如果出现以下情况,这种运气可能会改变:

  1. 您切换到其他承诺实现。

  2. 您在不同的平台上运行。承诺实现必须与各种平台提供给它们的工作一起工作。因此,每个平台的行为可能有所不同,这很好,只要它不违反规范。但是,规范不能保证初始代码所依赖的行为,因此可能无法在所有平台上维护它。

  3. 你使用的 promise 实现的新版本已发布,并且不再维护你所依赖的行为。

在我的机器和 CI 上,摩卡有可能使用不同的承诺实现吗?

查看摩卡的代码,我没有看到摩卡实例化承诺的任何位置。它检测it是否返回承诺,并依赖于承诺提供的 API,但它不会创建自己的承诺。

有没有办法强制摩卡兑现承诺?

见上文。它接收您返回的承诺,因此它使用您在测试套件中使用的任何实现。

也许更改后的 Promise 来自代码中的其他地方?

不确定你在那里是什么意思。

最新更新