如何编写Jasmine测试以验证异步回调是否不引发错误?
我正在用这个基本模式编写一个函数:
myFunction: function (callback) {
this.doSomethingAsync(function () {
if (callback) {
callback();
}
});
return "done";
}
参数callback
是可选的。因此,如果用户没有提供回调,if
语句将跳过回调。
如果有人在将来删除if
语句,我想写一个Jasmine测试失败。但是,我想不出如何构建测试。
删除if
语句并调用myFunction
的结果是Javascript引发了此TypeError
:
Uncaught TypeError: callback is not a function
但是,我无法想到如何设置Jasmine测试以验证是否没有引发此类错误。
答案 0 :(得分:2)
你可以存根doSomethingAsync函数,并让它只调用回调函数
describe('doSomthingAsync', function(){
function A(){
this.doSomethingAsync = function(cb){
setTimeout(function(){
cb();
},2000);
}
this.myFunction = function(cb){
this.doSomethingAsync(function(){
cb();
})
}
}
it('tests for the throws', function(){
var a = new A();
a.doSomethingAsync = function(cb){
cb();
}
var func = function(){
a.myFunction();
};
var func2 = function(){
a.myFunction(function(){
console.log('ping');
});
}
expect(func).toThrow(Error);
expect(func2).not.toThrow(Error);
});
});
尽管如此,我可能通过放置代码来检查回调是否在其他地方定义来强制执行回调是可选的这一事实。
...
this.doSomethingAsync = function(cb){
setTimeout(function(){
if(cb && typeof cb === 'function'){
cb();
}
//do other stuff
}, 2000)
}
答案 1 :(得分:1)
首先,您可以通过将相关函数模拟为同步执行来序列化异步部分。然后,您可以使用.not.toThrow()
期望来测试预期的行为。
假设这个演示对象:
var objUnderTest = {
doSomethingAsync: function(fn) {
console.info("Doing something async.");
setTimeout(function(){
console.info("Done something async.");
fn();
}, 1000);
},
myFunction: function(callback) {
this.doSomethingAsync(function() {
if (callback) {
callback();
}
});
return "done";
}
};
您的测试可能如下所示:
describe("Test", function(){
beforeEach(function(){
// serialize calls for easier testing
// now your closure passed to doSomethingAsync() will directly be called
spyOn(objUnderTest, "doSomethingAsync").and.callFake(function(fn){
fn();
});
});
it("should call the callback on myFunction(<callack>)", function() {
var callback = jasmine.createSpy("callback");
objUnderTest.myFunction(callback);
expect(callback).toHaveBeenCalled();
});
it("should not throw on myFunction() without callback", function(){
expect(function(){
objUnderTest.myFunction();
}).not.toThrow();
});
});
由于您只想测试myFunction
的行为是否正确,我认为模仿doSomethingAsync
即可,即使它是被测模块的一部分也是如此。
如果您不想在测试对象中模拟方法,则可以模拟doSomethingAsync()
方法调用的所有方法。
假设您需要模拟演示对象setTimeout()
:
spyOn(window, "setTimeout").and.callFake(function(fn){
fn();
});
答案 2 :(得分:0)
我在进行karma-jasmine测试时检查到我的库如果在超时之前没有发生正确的init会抛出异常,我就遇到了这个问题。虽然可以选择提供自己的process.on('uncaughtException', function (err) {
expect(....);
done();
})
,但我希望测试尽可能接近prod条件。我选择了这个
Q.ninvoke
在节点中你可以使用它(虽然没有经过测试)
var cuid = require('cuid');
var fs = require('fs');
var Q = require('q');
var AWS = require('aws-sdk');
var S3 = new AWS.S3();
module.exports = {
initialize: initialize
};
function initialize(options) {
return Q.nfcall(fs.readFile, options.path).then(function (file) {
var fileParams = {
Bucket: options.bucket,
Key: options.name,
Body: file,
ContentType: options.contentType
};
return Q.ninvoke(S3, 'upload', fileParams).then(function(data){
return data.Location;
});
});
}