【问题标题】:Angular/Mocha/Chai - initialize controller for unit testing?Angular/Mocha/Chai - 为单元测试初始化​​控制器?
【发布时间】:2015-08-18 16:09:35
【问题描述】:

我们刚刚开始在 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?
    });
});

【问题讨论】:

    标签: angularjs unit-testing mocha.js chai


    【解决方案1】:

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

    要测试服务,您可以使用 $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 来返回一个 Promise,你也可以使用 https://docs.angularjs.org/api/ng/service/$q 并解决,例如:

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

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

    【讨论】:

    • 感谢一百万!这正是我所缺乏的那种信息。
    猜你喜欢
    • 1970-01-01
    • 2015-10-03
    • 2016-06-14
    • 2023-03-10
    • 2023-04-11
    • 1970-01-01
    • 1970-01-01
    • 2018-11-05
    • 2016-05-26
    相关资源
    最近更新 更多