具有承诺的AngularJS单元测试控制器

时间:2016-04-05 13:18:28

标签: angularjs unit-testing jasmine karma-jasmine sinon

我在控制器中定义了以下代码

(function() {
    'use strict';

    angular
    .module('bolt')
    .controller('PackdownController', PackdownController);

    PackdownController.$inject = ['$location', '$timeout', 'packdownService', 'modelTransformer', 'Packdown'];

    function PackdownController($location, $timeout, packdownService, modelTransformer, Packdown) {
        var vm = this;  

        vm.totalItemCount = 0;
        vm.completedItemCount = 0;
        vm.toDoItems = [];
        vm.completedItems = [];

        activatePackdown();

        function activatePackdown() {
            packdownService.GetAllTasks().then(function(data) {
                if(data !== undefined && data !== null) {
                    if(data.error.state) {
                            showError('Error retrieving tasks', 'Please try again. If the problem persists, contact your supervisor', 'Close', toggleErrorModal);
                    }
                    else {               
                        vm.totalItemCount = tasks.openItems + tasks.closeItems;
                        vm.completedItemCount = tasks.closeItems;
                        angular.forEach(tasks.bayTasks, function(value, key) {
                            if(value.status.description !== 'COMPLETED_THIS_CYCLE') {
                                var task = {
                                        deptNbr: value.department.number,
                                        bayName: value.aisle + '-' + value.bay,
                                        status: {
                                            code: value.status.code,
                                            description: value.status.description
                                        }
                                };
                                this.push(task);
                            }
                        }, vm.toDoItems);
                        angular.forEach(tasks.bayTasks, function(value, key) {
                            if(value.status.description === 'COMPLETED_THIS_CYCLE') {
                                var task = {
                                        deptNbr: value.department.number,
                                        bayName: value.aisle + '-' + value.bay,
                                    completedBy: value.completedSystemUserId,
                                        completedOn:  new Date(value.completedTimeStamp)
                                };
                                this.push(task);
                            }
                        }, vm.completedItems);
                    }
                }

            });


        }

    }
})();

activatePackdown是一个私有函数,所以我不能直接测试它,但是我可以在创建控制器后测试公共属性的值。但是,由于该函数调用一个服务方法(返回一个promise),我不知道如何在.then语句中进行测试。我的单元测试有以下内容:

describe('activatePackdown', function(){            
    it('should call GetAllTasks and then set completed/total counts', function(done) {
        var spy = sinon.spy(this.packdownService, 'GetAllTasks');

        var ctlr = $controller('PackdownController');
        expect(spy).toHaveBeenCalled();
    });
});
.toHaveBeenCalled传递得很好,但是我试图用来测试.then中的属性状态。例如,vm.totalItemCount的值。我知道我实际上并不想让GetAllTask​​s方法运行,所以我使用sinon.spy创建了间谍,但我现在处于一个我不知道下一步该做什么的地步。我在不同的博客上尝试了几种不同的建议,但似乎没有任何效果。非常感谢任何和所有帮助

2 个答案:

答案 0 :(得分:1)

使用茉莉花, 我会模拟注入$ q和$ controller;

var deferred = $q.defer();
spyOn(Object, 'method').and.returnValue(deferred.promise);
controller.method(); //Calling your controller method

然后在那时测试你的成功

 $scope.$apply(function () {
    deferred.resolve(<insert expected object>);
 });

在出现错误时测试你的

$scope.$apply(function () {
   deferred.reject();
});

答案 1 :(得分:0)

仅供将来参考,这是我的工作测试现在的样子

it('should call GetAllTasks and then set completed/total counts', function() {
     var deferred = this.$q.defer();
     var stub = sinon.stub(this.packdownService, 'GetAllTasks').returns(deferred.promise);
     deferred.resolve(response);
     var ctlr = $controller('PackdownController');

     this.$timeout.flush();           
     expect(ctlr.totalItemCount).toEqual(4);
     this.$timeout.verifyNoPendingTasks();
});