我试图通过对其中一个依赖项进行存根来对单元进行单元测试,在本例中为numbers
该模块的简化版如下:
UserManager
我正在对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');
}
);
}
};
};
函数进行存根,该函数返回saveCode
,以便返回已解析的Promise,但当我Promise
assert
时已被调用,在断言res.redirect
尚未被调用时唉。
单元测试的简化版本是:
res.redirect
如何正确地保留承诺,以使被测方法同步运行?
答案 0 :(得分:2)
我使用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));
})
})
});
这很有效。
答案 1 :(得分:1)
嗯,最简单的事情就是不将其存根同步运行,因为这可能会改变执行顺序并使用Mocha内置的promises支持(或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这样的其他库允许你自己承担风险,但即使在让你这样做的图书馆可能不是最好的主意。