Jasmine controller check, expected spy that was called

I have a method defined in an AngularJS controller that gets called during initialization. I want to test it with Jasmine ( "jasmine-core": "^2.3.4", "karma": "^0.12.37" ). I am following some tutorials on the Internet and StackOverflow, but I cannot find the right answer. Please take a look at this code:

Controller usersAddUserController :

 (function () { 'use strict'; angular.module('app.users.addUser') .controller('usersAddUserController', ['$scope', 'usersAddUserService', function ($scope, usersAddUserService) { usersAddUserService.getCountryPhoneCodes().then(function (phoneCodes) { $scope.phoneCodes = phoneCodes; }); }]); }()); 

Jasmine Test:

 (function () { 'use strict'; describe('usersAddUserControllerUnitTest', function () { var scope, deferred, objectUnderTest, mockedAddUserService; beforeEach(module('app')); beforeEach(inject(function ($rootScope, $q, $controller) { scope = $rootScope.$new(); function emptyPromise() { deferred = $q.defer(); return deferred.promise; } mockedAddUserService = { getCountryPhoneCodes: emptyPromise }; objectUnderTest = $controller('usersAddUserController', { $scope: scope, usersAddUserService: mockedAddUserService }); })); it('should call getCountryPhoneCodes method on init', function () { //when spyOn(mockedAddUserService, 'getCountryPhoneCodes').and.callThrough(); deferred.resolve(); scope.$root.$digest(); //then expect(mockedAddUserService.getCountryPhoneCodes).toHaveBeenCalled(); }); }); }()); 

After running the test, the error message is:

PhantomJS 1.9.8 (Windows 7 0.0.0) usersAddUserControllerUnitTest should call the getCountryPhoneCodes method for init FAILED

  Expected spy getCountryPhoneCodes to have been called. 

Obviously, I missed something, but I can’t understand what it is. Any help would be appreciated.

+6
source share
2 answers

You monitor the layout after it has been passed to the instance controller.

Try the following:

 describe('usersAddUserControllerUnitTest', function () { var scope, deferred, objectUnderTest, mockedAddUserService, $controller; beforeEach(module('app')); beforeEach(inject(function ($rootScope, $q, _$controller_) { scope = $rootScope.$new(); function emptyPromise() { deferred = $q.defer(); return deferred.promise; } mockedAddUserService = { getCountryPhoneCodes: emptyPromise }; $controller = _$controller_; })); function makeController() { objectUnderTest = $controller('usersAddUserController', { $scope: scope, usersAddUserService: mockedAddUserService }); } it('should call getCountryPhoneCodes method on init', function () { //when spyOn(mockedAddUserService, 'getCountryPhoneCodes').and.callThrough(); makeController(); deferred.resolve(); scope.$root.$digest(); //then expect(mockedAddUserService.getCountryPhoneCodes).toHaveBeenCalled(); }); }); 

EDIT Thanks @juunas for noticing an error in my solution

+4
source

You can provide a layout like this:

 mockedAddUserService = { getCountryPhoneCodes: emptyPromise }; beforeEach(function () { module(function ($provide) { $provide.value('usersAddUserService', mockedAddUserService); }); }); 

EDIT:

The code should look like (as I can't verify it) like this:

 (function () { 'use strict'; describe('usersAddUserControllerUnitTest', function () { beforeEach(module('app')); var emptyPromise = function() { var deferred = $q.defer(); return deferred.promise; } var mockedAddUserService = { getCountryPhoneCodes: emptyPromise }; beforeEach(function () { module(function ($provide) { $provide.value('usersAddUserService', mockedAddUserService); }); }); var scope; beforeEach(inject(function ($rootScope, $q, $controller) { scope = $rootScope.$new(); $controller('usersAddUserController', { $scope: scope }); })); it('should call getCountryPhoneCodes method on init', function () { spyOn(mockedAddUserService, 'getCountryPhoneCodes').and.callThrough(); scope.$root.$digest(); expect(mockedAddUserService.getCountryPhoneCodes).toHaveBeenCalled(); }); }); }()); 
+1
source

All Articles