我有以下功能:
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)
返回结果,也没有传入从成功callBack retrieveData
传回的人员数据。
我的问题是: 这是测试callBack函数的正确方法吗?无论哪种方式,我做错了什么?
答案 0 :(得分:3)
好的,所以茉莉花在很多细微的方面很棘手,我认为你的代码存在两个主要问题
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();
})
})
});
})