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

Angular/Mocha/Chai - initialize controller for unit testing?

我们刚刚开始在 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 服务 运行 以及如何处理最终的 return 数据并不明显。我们已经尝试了 $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?
    });
});

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

要测试服务,您可以使用 $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_;
}));

如果你需要API代理return一个承诺,你也可以模拟它 https://docs.angularjs.org/api/ng/service/$q 并解决,例如:

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

如果你确实想一起测试它们,你可以对你调用的 API 函数进行监视,并让监视 return 一个已解决的承诺。