我最近遇到了一个奇怪的行为。我有一个包含大量测试的大项目,其中一些是以同步方式编写的,假设promise库是没有deferred
的那个。
然而,在我的机器上准备好环境(Mac OS X,nodeJS 0.12.18 - 我知道:()之后,测试似乎运行了不同的promise实现 - 这次使用延迟的async版本,因此跟随测试失败:
// 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
执行两个请求。
如果同步调用promise,则request
mock会在两次调用后恢复。如果异步调用promise,则第一次调用成功,但第二次调用失败,同时恢复存根( 第二次调用之前)。
我的问题是:
所有这些看起来都很奇怪,特别是当代码使用bluebird
作为主要的Promise库时......
答案 0 :(得分:1)
如果你所测试的内容在保证解决之前不能保证处于正确的测试状态,那么你应该在你的第二个片段中显示你的测试。 那是测试依赖于已解决的承诺的条件的正确方法。您的初始代码工作的事实是由于运气。请考虑以下代码:
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
会通过,但这只是运气,因为承诺并不保证它会起作用。如果出现以下情况,这个运气可能会改变:
您切换到其他承诺实施。
您在不同的平台上运行。承诺实现必须与各种平台提供的一致。因此,从平台到平台可能会有所不同,这很好,只要它不违反规范。但是,您的初始代码所依赖的行为不符合规范,因此可能无法在所有平台上维护。
您使用的新版本的promise实现已发布,不再维护您所依赖的行为。
有可能在我的机器和CI上,Mocha使用不同的promise实现吗?
看看Mocha的代码,我没有看到Mocha实例化承诺的任何位置。它检测it
是否返回一个承诺,并取决于承诺提供的API,但它不会创建自己的承诺。
有没有办法强制实施Mocha的承诺?
见上文。它接收您返回的承诺,因此它使用您在测试套件中使用的任何实现。
也许改变后的Promise来自代码中的另一个地方?
不确定你的意思。