Reputation: 6121
I have a mocked service, personService below, which is being called by the controller personController which is what I'm testing.
I want to test pass/fail paths obviously, so I'm trying to conditionally route the promise resolve/reject based on an input in my test, to test both paths.
// Mocking personService and its functions
beforeEach(inject(function($q) {
personService = {
addPerson: function (resolve) {
var deferred = $q.defer();
if(resolve) {
deferred.resolve();
}
else {
deferred.reject();
}
return deferred.promise;
}
};
// And add its spies
spyOn(personService, 'addPerson').and.callThrough();
}));
// Mocking $state
beforeEach(inject(function () {
$state = {
go: function () {
return true;
}
};
// And its spies
spyOn($state, 'go').and.callThrough();
}));
For this particular function, $state.go is called if the service call to addPerson is resolved, and is not called if it's rejected, so I'm laying out my test as below:
it("on return error from personService.add, state.go not called", function () {
$scope.addPerson(false);
$rootScope.$digest();
expect($state.go).not.toHaveBeenCalled();
});
it("on return success from personService.add, state.go called", function () {
$scope.addPerson(true);
$rootScope.$digest();
expect($state.go).toHaveBeenCalled();
});
In the first test I'm passing false, which should reject the promise, and not call $state.go ... however when the test is actually ran the spy is called on $state.go!
For reference, the controller function in question is below:
var _addPerson = function () {
personService.addPerson().then(function (response) {
$state.go('home.person', { personIndex: $scope.personList.length }, { reload: true });
_gotoLastPerson();
}),
function (err) {
console.log(err);
};
};
A perplexing note which indicates I'm close... if I remove the if/then from addPerson and always just deferred.reject() then the first test passes, and the second fails; exact reverse happens if I always deferred.resolve().
1) How to use a conditional $q resolve/reject in a Jasmine mocked service call
Update
After searching around it seems some people put all of this setup within the it() blocks themselves, in which case I could just change the service to explicitly resolve or reject depending on which it() it's in... but that seems like horrible coding practices.
Upvotes: 0
Views: 730
Reputation: 6121
Hooray! Okay so I don't know why this was happening yet, but the resolve in addPerson: function (resolve)
was actually the person object instead of the boolean.
So instead I created a global var resolvePromise which I set to true/false depending on my need and it works beautifully.
Upvotes: 0