Angular / Mocha / Chai - 初始化控制器进行单元测试?

时间:2015-08-18 16:09:35

标签: angularjs unit-testing mocha chai

我们刚开始使用Angular应用程序中的单元测试,我们正在使用karma / mocha / chai框架进行单元测试。我对我们定义的各种服务和工厂进行了一些基本的单元测试,单元测试工作得很好。但是现在我们要测试一些控制器并评估控制器正在修改的范围变量。

这是一个这样的控制器的例子:

angular.module('App').controller('myCtrl', ['$scope', 'APIProxy', 
    function ($scope, APIProxy) {
        $scope.caseCounts = {caseCount1: 0, caseCount2: 0};

        $scope.applyCounts = function () {
            $scope.caseCounts.caseCount1 = {...some case count logic...}
            $scope.caseCounts.caseCount2 = {...some case count logic...}
        };

        APIProxy.getAll().then(function (data) {
            {...do a bunch of stuff...}
            $scope.data = data;
            $scope.applyCounts();
        });
    }]
);

现在,当我进行单元测试时,我想从一个简单的'开始'$ scope.caseCounts具有值> 0,然后我将从那里建造。但是,如何使控制器导致APIProxy服务运行以及如何处理最终的数据返回并不明显。我们已经尝试了$ scope.getStatus()和$ scope.apply()以及其他一些东西,但我觉得我们已经偏离了标准,我们从根本上错过了一些关于如何解决这个问题的事情。

目前我们的控制器测试仪看起来像:

describe("myCtrl unit tests",function(){
    beforeEach(module('App'));

    var ctrl, APIProxy;

    beforeEach(inject(function ($rootScope, $controller, _APIProxy_)
        {
            $scope = $rootScope.$new();
            APIProxy = _APIProxy_;
            ctrl = $controller('myCtrl', {$scope: $scope, APIProxy: APIProxy});
    }));

    it('Loads data correctly', function() {
        expect(ctrl).to.not.be.undefined;
        //??? what else do we do here to fire the getAll function in controller?
    });
});

1 个答案:

答案 0 :(得分:2)

分别测试服务和控制器通常会更好。

要测试服务,您可以使用$ httpBackend来模拟XHR请求:

https://docs.angularjs.org/api/ngMock/service/$httpBackend

要测试控制器,您可以在初始化控制器时提供模拟值而不是实际服务

APIProxy = {'mocked':'data'};
ctrl = $controller('myCtrl', {$scope: $scope, APIProxy: APIProxy});

或者更一般地说,模拟模块的任何提供者:

module(function($provide) {
  $provide.constant('ab','cd');
  $provide.value('ef', 'gh');
  $provide.service('myService', function() { });
});

这会覆盖' myService'在控制器中引用为依赖项(如果有的话)。如果你需要它,你也可以注入它:

var myService;
beforeEach(inject(function (_myService_) {
    myService = _myService_;
}));

如果您需要APIProxy返回承诺,您也可以使用它来模拟它 https://docs.angularjs.org/api/ng/service/$q 并解决,例如:

var deferred = $q.defer();
deferred.resolve({'mocked':'data'});
return deferred.promise;

如果您确实想要一起测试它们,您可以对您调用的API函数进行间谍,并让间谍返回已解决的承诺。