Angular/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?
    });
});

person Gatmando    schedule 18.08.2015    source источник


Ответы (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 возвращал обещание, вы также можете смоделировать его с помощью https://docs.angularjs.org/api/ng/service/$q и решить, например:

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

Если вы хотите протестировать их вместе, вы можете шпионить за функцией API, которую вы вызываете, и заставить шпиона возвращать разрешенное обещание.

person pansay    schedule 19.08.2015
comment
Бесконечно благодарен! Это была именно та информация, которой мне не хватало. - person Gatmando; 20.08.2015