unit testing tutorial Почему $ предоставляется только в функции «angular.mock.module», а $ q доступен только в функции «angular.mock.inject»?




mock angularjs (2)

Я издеваюсь над службой для теста UnitularJS Unit. Я использую службу $provide provision, чтобы заменить «настоящую» услугу на издеваемую (скрипт plunker этого доступен):

describe('My Controller', function () {

    var $scope;
    var $provide;

    beforeEach(angular.mock.module('myApp'));

    beforeEach(angular.mock.module(function (_$provide_) {

        $provide = _$provide_;

    }));

    beforeEach(angular.mock.inject(function($rootScope, $controller, $q){

        var mockMyService = {
            getAll : function() {
                var deferred = $q.defer();
                deferred.resolve([
            { itemText: "Foo" },
            { itemText: "Bar" }
                ]);

                return deferred.promise;
            }
        };

        $provide.value('myService', mockMyService);

        $scope = $rootScope.$new();

        $controller('MyCtrl', { $scope: $scope });

        $rootScope.$apply();

    }));

    it('Has two items defined', function () {
        expect($scope.items.length).toEqual(2);
    });
});

Это прекрасно работает. Тем не менее, мне не нравится тот факт, что я использую функцию angular.mock.module просто для указания ссылки на службу $provide angular.mock.inject которая затем используется в функции angular.mock.inject ниже. Но если я добавлю $provide как параметр функции angular.mock.inject непосредственно, я получаю ошибку «неизвестного провайдера».

Мне приходит в голову, что я могу поместить весь издевательский код в функцию angular.mock.module . Но тогда у меня есть аналогичная проблема с ссылкой на $q , которая мне нужна, поскольку мой издевавшийся сервис должен вернуть обещание.

Другими словами, если я добавлю параметр $q в функцию angular.mock.module я также получаю ошибку «неизвестного провайдера».

Есть ли способ упростить это? Очевидно, что у меня есть работы, но это не совсем правильно. Я чувствую, что мне не хватает понимания того, почему некоторые поставщики доступны для inject а другие доступны в module функциях.


Это работало для меня, когда мне пришлось обернуть службу, которая использовала $q и выглядела довольно чистой:

var _ServiceToTest_;
beforeEach(function () {
    module('module.being.tested');
    module(function ($provide) {
        $provide.factory('ServiceToMock', function ($q, $rootScope) {
            var service = ...;
            // use $q et al to heart's content
            return service;
        });
    });
    inject(function (_ServiceToTest_) {
        ServiceToTest = _ServiceToTest_;
    });
});

it('...', function () { /* code using ServiceToTest */ });

Трюк состоял в том, чтобы использовать $provide.factory вместо $provide.value .


Вы не можете использовать $provide в функции inject потому что прежний регистрирует поставщиков для использования последними. Взглянуть:

describe('...', function() {
    beforeEach(function() {
        module(function($provide) {
            $provide.constant('someValue', 'foobar');
        });

        inject(function(someValue) {
            var value = someValue; // will be 'foobar';
        });
    });
});

Вы можете написать свой тест следующим образом:

describe('...', function() {
    var serviceMock;

    beforeEach(function() {
        serviceMock = {
           someMethod: function() { ... }
        };

        module(function($provide) {
            $provide.value('service', serviceMock);
        });

        inject(function(service) {
            ...                         
        });
    });
});

На самом деле вам даже не нужно внедрять издеваемую службу, прежде чем вводить ее с помощью $provide :

beforeEach(function() {
    serviceMock = {};

    module(function($provide) {
        $provide.value('service', serviceMock);
    });

    inject(function(service) {
        ...                         
    });
});

it('tests something', function() {
    // Arrange
    serviceMock.someMethod = function() { ... }

    // Act
    // does something

    // Assert
    expect(...).toBe(...);
});

Вот сценарий Plunker, иллюстрирующий в основном вышеизложенное.





jasmine