2016-08-05 2 views
0

У меня есть два контроллера и служба. В первом контроллере я подписался на мероприятие, чтобы сделать что-то. Второй контроллер выполняет некоторые действия, и когда это делается, транслирует событие. См. Пример ниже, тайм-аут предназначен только для эмуляции длительных действий. Я хотел бы проверить, что hasLoaded установлен в true, используя Jasmine 2.0. Пожалуйста, сообщите.Как проверить действия, которые выполняются при обратном вызове с помощью Jasmine

var myApp = angular.module('MyApp', []); 
 

 
myApp.controller('MyCtrl1', ['$scope', 'myService', function($scope, myService) { 
 
    $scope.hasLoaded = false; 
 
    $scope.fileName = ''; 
 
    
 
    myService.onLoaded($scope, function(e, data){ 
 
     // I want to test the following two lines, in the really the code here is much more complex 
 
     $scope.fileName = data.fileName; 
 
     $scope.hasLoaded = true; 
 
    }); 
 
}]); 
 

 
myApp.controller('MyCtrl2', ['$rootScope', '$scope', '$timeout', 'myService', function($rootScope, $scope, $timeout, myService) { 
 
    $scope.isLoading = false; 
 
    $scope.title = 'Click me to load'; 
 

 
    $scope.load = function(){ 
 
     $scope.isLoading = true; 
 
     $scope.title = 'Loading, please wait...'; 
 
     
 
     $timeout(function() { 
 
      $rootScope.$emit('loaded', { fileName: 'test.txt'}); 
 
     }, 1000); 
 
    }; 
 

 
    myService.onLoaded($scope, function(){ 
 
     $scope.hasLoaded = true; 
 
    }); 
 
}]); 
 

 
myApp.service('myService', ['$rootScope', function ($rootScope) { 
 
    this.onLoaded = function(scope, callback) { 
 
     var handler = $rootScope.$on('loaded', callback); 
 
     scope.$on('$destroy', handler); 
 
    }; 
 
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js"></script> 
 

 
<div ng-app="MyApp"> 
 
    <div ng-controller="MyCtrl1"> 
 
     <div ng-show="hasLoaded">{{fileName}} loaded !!!</div> 
 
    </div> 
 
    <div ng-controller="MyCtrl2"> 
 
     <button ng-click="load()" ng-hide="hasLoaded" ng-disabled="isLoading" ng-bind="title"></button> 
 
    </div> 
 
</div>

UPDATE: Я добавил параметр в широковещательный вызов, чтобы сделать его более ближе к моему делу.

ответ

2

Вы действительно должны тестировать каждую из своих частей (контроллеров и служб) отдельно. В вашем случае, тесты для контроллера, который устанавливает hasLoaded правильно на самом деле просто нужно проверить, что ваш реестр с сервисом правильно и что обратного вызова делает то, что вы ожидаете:

it("should register with the service and do the right thing when the callback is executed", inject(function ($controller, $rootScope, myService) { 
     var $scope = $rootScope.$new(); 
     spyOn(myService, 'onLoaded').and.callThrough(); 

     var ctrl = $controller('MyCtrl1', {$scope: $scope, myService: myService}); 
     $scope.$apply(); 

     //verify that the controller registers its scope with the service 
     expect(myService.onLoaded).toHaveBeenCalledWith($scope, jasmine.any(Function)); 
     //now call the callback that was registered to see if it sets the property correctly 

     var mockData = { 
      fileName: 'some file name' 
     }; 
     myService.onLoaded.calls.argsFor(0)[1]('loaded', mockData); 
     expect($scope.hasLoaded).toBeTruthy(); 
     expect($scope.fileName).toBe("some file name"); 
    })); 

Затем написать тесты для вашей службы и других контроллер отдельно.

+0

Спасибо, это то, что мне нужно. Не могли бы вы рассказать мне, почему нам нужно иметь $ scope. $ Apply(); вызов? – Antipod

+0

На самом деле вы этого не делаете. Я просто привык делать это, потому что в последнее время я тестировал макет обещаний, для которых требуется $ apply(), чтобы быть разрешенным в тесте. – mcgraphix

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

  • Нет связанных вопросов^_^