2016-08-05 5 views
0

두 개의 컨트롤러와 서비스가 있습니다. 첫 번째 컨트롤러에서는 이벤트를 구독하여 물건을 처리했습니다. 두 번째 컨트롤러는 일부 동작을 수행하고 완료되면 이벤트를 브로드 캐스팅합니다. 아래의 예제를 참조하십시오. 타임 아웃은 장시간 실행되는 동작을 에뮬레이션하기위한 것입니다. 테스트하고 싶습니다. hasLoaded은 Jasmine 2.0을 사용하여 true로 설정하십시오.재스민을 사용하여 콜백에서 수행되는 작업을 테스트하는 방법

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

정말로 각 조각 (컨트롤러 및 서비스)을 개별적으로 테스트해야합니다. 서비스 및 기타에 대한

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

그리고 쓰기 테스트 : 당신의 경우, hasLoaded을 설정하는 컨트롤러에 대한 테스트가 제대로 정말 그냥 콜백 제대로 서비스와 당신의 레지스터는 당신이 무엇을 기대한다는 것을 테스트 할 필요가있다 컨트롤러 별도.

+0

감사합니다. 이것이 내가 필요한 것입니다. 왜 우리가 $ scope을 가질 필요가 있는지 말해 주시겠습니까? $ apply(); 요구? – Antipod

+0

당신은 실제로 당신의 경우에는하지 않습니다. 최근에는 테스트에서 해결하기 위해 $ apply()를 요구하는 mock 약속으로 테스트를했기 때문에 그 일을하는 데 익숙합니다. – mcgraphix

관련 문제