使用jasmine测试JavaScript回调函数
Testing JavaScript callback functions with jasmine
我有以下功能:
function getPersonData(id) {
retrieveData(
id,
function(person) {
if(person.name) {
displayPerson(person);
}
}
}
function retrieveData(id, successCallBack) {
executeRequest(id, {
success: successCallBack
});
}
getPersonData
根据id检索人员的信息。它又通过传入id和successCallBack函数来调用retrieveData
。
retrieveData
获取id和successCallBack并调用另一个函数executeRequest
,该函数获取数据并传递回一个person对象。
我正在尝试测试getPersonData
,并设置以下规范
describe("when getPersonData is called with the right person id", function() {
beforeEach(function() {
spyOn(projA.data, "retrieveData").and.returnValue(
{
'name': 'john'
}
);
spyOn(projA.data, "displayPerson");
projA.data.getPersonData("123");
});
it("displays the person's details", function() {
expect(projA.data.displayPerson).toHaveBeenCalled();
);
});
但是在执行规范时,不会调用displayPerson
方法。这是因为从成功回调function(person)
返回的人员数据没有被传入,即使我已经嘲笑retrieveData
返回结果。
我的问题是:这是测试回调函数的正确方法吗?不管怎样,我做错了什么?
好的,所以jasmine在很多微妙的方面都很棘手,我认为你的代码有两个主要问题
- 有太多的异步调用被包裹在一起。这本身不是问题,但它让在JASMINE地狱中的测试变得更加困难。例如,有一个
retrieveData
函数,它只调用参数完全相同但方式略有不同的executeRequest
函数,这有什么意义
我把你的getPersonData改写成这个
function getPersonData(id) {
// this is needed to properly spy in Jasmine
var self = this;
//replaced retrieveData with just execute request
// self is required to properly spy in Jasmine
self.executeRequest(id, {
success: function(person) {
if (person.name) {
self.displayPerson(person);
}
}
})
}
//I don't know what exactly executeRequest does
//but I took the liberty to just make it up for this example
function executeRequest(id, callback) {
callback.success({
name: id
});
}
//I also assumed that projA would look something like this
var projA = {
data: {
getPersonData: getPersonData,
retrieveData: retrieveData,
displayPerson: displayPerson,
executeRequest: executeRequest
}
};
2.为了在Jasmine中测试异步代码,您需要在测试中包含一个done
回调。此外,如果希望回调函数自动启动,则需要在setTimeout
函数中设置它,否则它永远不会启动。这里有一个调整后的例子:
describe("when getPersonData is called with the right person id", function() {
beforeEach(function() {
//you should not spyOn retriveData or executeCode because it will override the function you wrote and will never call displayPerson
// you should only have spies on the methods you are testing otherwise they will override other methods
spyOn(projA.data, "displayPerson");
});
it("displays the person's details", function(done) {
// it's better to call the function within specific test blocks so you have control over the test
projA.data.getPersonData("123");
// at this point, it will just have called the getPersonData but will not call executeRequest
setTimeout(function() {
//this block will just call executeRequest
setTimeout(function() {
//this block will finally call displayPerson
expect(projA.data.displayPerson).toHaveBeenCalled();
//tell jasmine the test is done after this
done();
})
})
});
})
相关文章:
- JavaScript回调函数
- 如何在回调函数中执行流
- 回调函数中传递参数的困难(Google Map API Markers)
- 如何正确地将参数传递给RequireJS回调函数
- 回调函数在python代码中离线
- 从AJAX回调函数中分离数据
- 赋值后的回调函数
- 如何在javascript回调函数中返回多个变量
- 函数表达式,返回回调函数
- 等待回调函数执行
- JavaScript回调函数和Google Feed API
- 如何从ajax成功回调函数中读取javascript变量
- 正在保存JavaScript内部回调函数中的值
- 有没有什么方法可以停止Jquery中的animate(也可以停止完整的回调函数)
- 如何在javascript中添加带有回调函数的按钮点击事件作为window.conf
- 在Golang回调函数中启用CORS
- 在初始函数完成之前调用回调函数
- jQuery Mobile:如何在$.Mobile.changePage之前运行回调函数
- 即使使用回调函数也无法返回值
- 为什么prototypjs观察到回调函数有绑定