如何使用Jasmine

时间:2016-08-05 16:10:13

标签: angularjs jasmine angular-services

我有两个控制器和一个服务。在第一个控制器中,我订阅了一个事件来做一些事情。第二个控制器执行一些操作,一旦完成,就广播事件。请参阅下面的示例,超时仅用于模拟长时间运行的操作。我想测试使用Jasmine 2.0将 hasLoaded 设置为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>

更新:我已在广播调用中添加了参数,使其更接近我的情况。

1 个答案:

答案 0 :(得分: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");
    }));

然后分别为您的服务和其他控制器编写测试。