2015-07-03 3 views
6

У меня есть метод, определенный в контроллере AngularJS, который вызывается при инициализации. Я хочу протестировать его с помощью Jasmine ("jasmine-core": "^2.3.4", "karma": "^0.12.37"). Я следую некоторым учебникам по вопросам Интернета и StackOverflow, но я не могу найти правильный ответ. Пожалуйста, обратите внимание на этот код:Проверка контроллера жасмина, ожидаемый шпион, который был вызван

контроллер usersAddUserController:

(function() { 
    'use strict'; 

    angular.module('app.users.addUser') 
     .controller('usersAddUserController', ['$scope', 'usersAddUserService', function ($scope, usersAddUserService) { 

      usersAddUserService.getCountryPhoneCodes().then(function (phoneCodes) { 
       $scope.phoneCodes = phoneCodes; 
      }); 

     }]); 
}()); 

Жасмин тест:

(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(); 
     }); 

    }); 
}()); 

После запуска тестов, сообщение об ошибке:

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

Expected spy getCountryPhoneCodes to have been called. 

I явно чего-то не хватает, но я не могу понять, что это такое. Любая помощь будет оценена.

ответ

3

Вы шпионит макет после того, как он был передан в экземплярный контроллер.

Попробуйте это:

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 Благодарности @juunas для заметив ошибку в моем решении

+0

Благодарим вас за ответ, но, к сожалению, по-прежнему вы получаете ту же ошибку с кодом. Он работает на вас? –

+0

Я действительно не пробовал, он выглядел как очевидная проблема. Можете ли вы поставить точку останова на свой конструктор контроллера и посмотреть, действительно ли это тот шпион, с которым он звонит? – Martin

+0

Спасибо, ребята! Действительно, @juunas был прав, я получил УСПЕХ теперь. Если juunas согласен, я все равно соглашусь с ответом Martin, это мне очень помогает :) –

1

Вы можете предоставить макет так:

mockedAddUserService = { 
    getCountryPhoneCodes: emptyPromise 
}; 


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

EDIT:

Код должен выглядеть (как я не могу проверить его), как это:

(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(); 
     }); 

    }); 
}()); 
+0

Спасибо за ответ, но не могли бы вы предоставить полный код? Когда я включаю ваше решение в свой код, я получаю: «TypeError:« undefined »не является объектом (оценка« deferred.resolve »)». –

+0

Благодарим вас за код, я попробую ваше решение и даю отзывы о том, что нужно делать больше. –

Смежные вопросы