![](/img/trans.png)
[英]How can I traverse an promise object reference chain synchronously in a loop
[英]How can I stub a Promise such that my test can be run synchronously?
我试图通过对其中一个依赖项(在本例中为UserManager
进行存根来对模块进行单元测试
该模块的简化版本如下:
// CodeHandler
module.exports = function(UserManager) {
return {
oAuthCallback: function(req, res) {
var incomingCode = req.query.code;
var clientKey = req.query.key;
UserManager.saveCode(clientKey, incomingCode)
.then(function(){
res.redirect('https://test.tes');
}).catch(function(err){
res.redirect('back');
}
);
}
};
};
我捻熄的UserManager的saveCode
它返回一个函数Promise
,使得它返回一个解决的承诺,但是当我assert
这res.redirect
被调用,唉,在断言的时间res.redirect
尚未被调用。
单元测试的简化版本是:
// test
describe('CodeHandler', function() {
var req = {
query: {
code: 'test-code',
key: 'test-state'
}
};
var res = {
redirect: function() {}
};
var expectedUrl = 'https://test.tes';
var ch;
beforeEach(function() {
sinon.stub(UserManager, 'saveCode').returns(
new RSVP.Promise(function(resolve, reject){
resolve();
})
);
sinon.stub(res, 'redirect');
ch = CodeHandler(UserManager);
});
afterEach(function() {
UserManager.saveCode.restore();
res.redirect.restore();
});
it('redirects to the expected URL', function(){
ch.oAuthCallback(req, res);
assert(res.redirect.calledWith(expectedUrl));
})
});
如何正确地保留承诺,以便被测方法同步运行?
我已经使用sinon-stub-promise
制定了一个解决方案。
describe('CodeHandler', function() {
var req = {
query: {
code: 'test-code',
key: 'test-state'
}
};
var ch;
var promise;
var res = {
redirect: function() {}
};
beforeEach(function() {
promise = sinon.stub(UserManager, 'saveCode').returnsPromise();
ch = CodeHandler(UserManager);
sinon.stub(res, 'redirect');
});
afterEach(function() {
UserManager.saveCode.restore();
res.redirect.restore();
});
describe('can save code', function() {
var expectedUrl = 'https://test.tes';
beforeEach(function() {
promise.resolves();
});
it('redirects to the expected URL', function(){
ch.oAuthCallback(req, res);
assert(res.redirect.calledWith(expectedUrl));
});
});
describe('can not save code', function() {
var expectedUrl = 'back';
beforeEach(function() {
promise.rejects();
});
it('redirects to the expected URL', function(){
ch.oAuthCallback(req, res);
assert(res.redirect.calledWith(expectedUrl));
})
})
});
这非常有效。
好吧,最简单的事情就是不要将它存根同步运行,因为这可能会改变执行顺序并使用Mocha内置的promises支持(如果使用jasmine则使用jasmine-as-promised)。
原因是可能会出现以下情况:
somePromise.then(function(){
doB();
});
doA();
如果你使promises同步解决执行顺序 - 从而输出程序发生变化,使测试变得毫无价值。
相反,您可以使用测试语法:
describe("the test", () => { // use arrow functions, node has them and they're short
it("does something", () => {
return methodThatReturnsPromise().then(x => {
// assert things about x, throws will be rejections here
// which will cause a test failure, so can use `assert`
});
});
});
您可以为单行使用更轻的箭头语法,这使得测试更简洁:
describe("the test", () => { // use arrow functions, node has them and they're short
it("does something", () =>
methodThatReturnsPromise().then(x => {
// assert things about x, throws will be rejections here
// which will cause a test failure, so can use `assert`
});
);
});
在RSVP中,你无法设置调度程序,因此无论如何都不可能同步测试事物,像bluebird这样的其他库允许你自己承担风险,但即使在允许你这样做的库中它也可能不是最好的主意。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.