I'm trying to test a controller that calls a method on a service. The service method returns a promise, and the controller immediately invokes .then()
inline after calling the service method. I'm trying to stub the service using sinon and Jasmine keeps throwing an error saying that then
is undefined and not a function.
Here is the controller:
var loginModalController = function ($scope, authenticationService) {
this.submit = submit;
function submit(user, password) {
$scope.email = user;
authenticationService.login(user, password)
.then(handleSuccessLogin, handleErrorLogin);
}
}
Here is the service:
function authenticationService($http, $q, endPointService) {
var baseUri = endPointService.getApiEndpoint();
var service = {
getTermsAndConditions: getTermsAndConditions,
login: login,
acceptTerms: acceptTerms
};
return service;
function getTermsAndConditions() {
...
};
function login(user, password) {
var deferred = $q.defer();
$http({ method: 'POST', url: baseUri + '/api/tokens', data: { username: user, password: password } }).
success(function (data, status, headers, config) {
$http.defaults.headers.common.Authorization = 'Basic ' + data.EncryptedTokenId;
deferred.resolve(data);
}).
error(function (data, status, headers, config) {
deferred.reject(status);
});
return deferred.promise;
};
function acceptTerms() {
...
};
}
And here is the test:
describe('loginModalController', function () {
var scope, loginModalController, authenticationServiceMock, localSaverServiceMock;
var loginInformationMock = { 'firstName': 'Testuser' };
beforeEach(function () {
module('clientAppModule');
inject(function ($rootScope, $controller, authenticationService, localSaverService) {
scope = $rootScope.$new();
authenticationServiceMock = sinon.stub(authenticationService)
.login.returns({ then: function () { return loginInformationMock } });
localSaverServiceMock = sinon.stub(localSaverService);
loginModalController = $controller('loginModalController', {
$scope: scope,
$state: {},
authenticationService: authenticationServiceMock,
errorCodes: {},
localSaverService: localSaverServiceMock
});
});
});
it('should login', function () {
loginModalController.submit("test", "test");
});
});
Four issues with my code:
stub()
rather than just letting it stub the service.$q
to return a deferred promise to match the login function.$digest()
on the scope to get the deferred promise to resolve before asserting.So here is the fixed test code: