Javascript 带有承诺和间谍的单元测试
我有以下文件:- target.jsJavascript 带有承诺和间谍的单元测试,javascript,node.js,unit-testing,promise,sinon,Javascript,Node.js,Unit Testing,Promise,Sinon,我有以下文件:- target.js var target = function(repository, logger) { return { addTarget : function(target) { repository.add(target).then( function (newTarget) { console.log("added");
var target = function(repository, logger) {
return {
addTarget : function(target) {
repository.add(target).then(
function (newTarget) {
console.log("added");
logger.info("added");
},
function (err) {
console.log("error");
logger.info("error");
}
);
}
};
};
module.exports = target;
var chai = require("chai"),
expect = chai.expect,
sinon = require("sinon"),
Promise = require("bluebird"),
baseTarget = require("../target");
describe("target", function(){
it("should log error when it occurs", function() {
var mockRepository = {
add : sinon.stub().returns(Promise.reject(new Error()))
};
var mockLogger = {
info : sinon.spy()
};
var target = baseTarget(mockRepository, mockLogger);
target.addTarget("target");
expect(mockLogger.info.calledWith("error")).to.be.true;
});
});
targetTest.js
var target = function(repository, logger) {
return {
addTarget : function(target) {
repository.add(target).then(
function (newTarget) {
console.log("added");
logger.info("added");
},
function (err) {
console.log("error");
logger.info("error");
}
);
}
};
};
module.exports = target;
var chai = require("chai"),
expect = chai.expect,
sinon = require("sinon"),
Promise = require("bluebird"),
baseTarget = require("../target");
describe("target", function(){
it("should log error when it occurs", function() {
var mockRepository = {
add : sinon.stub().returns(Promise.reject(new Error()))
};
var mockLogger = {
info : sinon.spy()
};
var target = baseTarget(mockRepository, mockLogger);
target.addTarget("target");
expect(mockLogger.info.calledWith("error")).to.be.true;
});
});
我遇到的问题是
expect(mockLogger.info.calledWith(“error”)).to.be.true
返回false
,因为存储库上的add
方法是异步的,所以尚未执行。是否有一种模式可以正确地做到这一点。这实际上更多的是一个关于“承诺如何工作”的问题,而不是它们在测试框架中如何工作的问题——答案是它们的行为保持完全相同
是否有一种模式可以正确地执行此操作
这与其说是一种模式,不如说是承诺的目的。的每个成功处理程序在最后一个成功时按顺序执行。在您的代码中,我们可以返回通过调用存储库#add
创建的承诺,就像您希望使用其结果或在addTarget
之外执行一些外部相关操作一样:
addTarget: function (target) {
return repository
// ^^^^^^
.add(target)
.then(function (newTarget) {
console.log("added");
logger.info("added");
}, function (err) {
console.log("error");
logger.info("error");
});
}
target.addTarget("target").then(function () {
expect(mockLogger.info.calledWith("error")).to.be.true;
cb();
});
然后将您的期望放在中,然后在addTarget
中创建的承诺链的所有成员成功后执行该:
addTarget: function (target) {
return repository
// ^^^^^^
.add(target)
.then(function (newTarget) {
console.log("added");
logger.info("added");
}, function (err) {
console.log("error");
logger.info("error");
});
}
target.addTarget("target").then(function () {
expect(mockLogger.info.calledWith("error")).to.be.true;
cb();
});
异步测试
var target = function(repository, logger) {
return {
addTarget : function(target) {
repository.add(target).then(
function (newTarget) {
console.log("added");
logger.info("added");
},
function (err) {
console.log("error");
logger.info("error");
}
);
}
};
};
module.exports = target;
var chai = require("chai"),
expect = chai.expect,
sinon = require("sinon"),
Promise = require("bluebird"),
baseTarget = require("../target");
describe("target", function(){
it("should log error when it occurs", function() {
var mockRepository = {
add : sinon.stub().returns(Promise.reject(new Error()))
};
var mockLogger = {
info : sinon.spy()
};
var target = baseTarget(mockRepository, mockLogger);
target.addTarget("target");
expect(mockLogger.info.calledWith("error")).to.be.true;
});
});
在上面的示例中,您会注意到还有一个对函数cb
的调用。由于您的测试是异步的,您需要在测试完成时“告诉”测试框架。这通常是通过使用参数声明it
函数来实现的,框架将根据该参数推断测试是异步的,并传入回调:
describe("target", function () {
it("should log error when it occurs", function (cb) {
// ^^^^
});
});