I have the following functions:
function getPersonData(id) {
retrieveData(
id,
function(person) {
if(person.name) {
displayPerson(person);
}
}
}
function retrieveData(id, successCallBack) {
executeRequest(id, {
success: successCallBack
});
}
getPersonData
retrieves a person's information based on the id. It in turn calls retrieveData
by passing in the id and a successCallBack function.
retrieveData
takes the id and successCallBack and calls another function, executeRequest
, which gets the data and passes back a person object.
I am trying to test getPersonData
and have the following spec set up
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();
);
});
But when the spec is executed the displayPerson
method isn't called. This is because the person data being passed back from the success callBack function(person)
isn't being passed in even though I have mocked retrieveData
to return a result.
My question is: Is this the right way to test callBack functions? Either way what am I doing wrong?
Ok, so jasmine is tricky in a lot of subtle ways and I think there's two main issues with your code
retrieveData
function which just callsexecuteRequest
function with the exact same parameters but in a slightly different way.I rewrote your getPersonData to be like this
2. In order to test asynchronous code in Jasmine, you need to include a
done
callback with the test. Also, if you expect a callback function to fire automatically, you need to set it up within asetTimeout
function, otherwise it will never fire. Here's an adjusted example: