21

我正在尝试测试一个依赖于我自己构建的服务的控制器。我想模拟这个服务,因为该服务与 DOM 对话。

这是我目前的测试:

describe('Player Controllers', function () {

    beforeEach(function () {
        this.addMatchers({
            toEqualData: function (expected) {
                return angular.equals(this.actual, expected);
            }
        });
    });

    describe('TestPSPlayerModule', function () {
        var $httpBackend, scope, ctrl;

        beforeEach(module('PSPlayerModule'));

        beforeEach(inject(function (_$httpBackend_, $rootScope, $controller) {
            $httpBackend = _$httpBackend_;

            scope = $rootScope.$new();
            ctrl = $controller(PlayerController, { $scope: scope });
        }));

        it('should request a clip url from the server when clipClicked is called', function () {
            expect(1).toBe(1);
        });
    });

});

我的控制器如下所示:

w.PlayerController = function ($scope, $http, $window, speedSlider, $location) {
    ...
}

所以这是我要模拟的speedSlider。

我有想法使用我在测试代码中创建的模块,它可以提供速度滑块的伪造实现,所以我在 test.js 文件的顶部添加了以下内容:

module('TestPSPlayerModule', []).factory('speedSlider', function () {
    return = {
       ...
    };
});

然后在 beforeEach() 调用而不是具体的调用中列出该模块,但如果我这样做,我会收到以下错误:

Injector already created, can not register a module!

所以我认为必须有更好的方法来提供我的一项服务的模拟实现。我也许可以将 sinon.js 用于....

4

4 回答 4

40

还要确保您没有尝试在注入函数调用中执行此操作:

这将引发错误:

    beforeEach(inject(function(someOtherService) {
        module('theApp', function($provide) {
            myMock = {foo: 'bar'};
            $provide.value('myService', myServiceMock);
            someOtherService.doSomething();
        });
    }));

这不会:

    beforeEach(function() {
        module('theApp', function($provide) {
            myMock = {foo: 'bar'};
            $provide.value('myService', myServiceMock);
        });

        inject(function(someOtherService) {
           someOtherService.doSomething();
        });
    });
于 2013-09-05T13:58:55.233 回答
6

确保在定义后使用模块时没有多余的括号。所以module('TestPSPlayer')代替module('TestPSPlayer',[]).

于 2012-07-12T21:38:13.843 回答
4

就我而言,这没有用:

beforeEach(module('user'));
beforeEach(inject(function ($http) {
}));

beforeEach(module('community'));
beforeEach(inject(function ($controller, $rootScope) {
}));

我已更改为此以使其正常工作:

beforeEach(module('user'));
beforeEach(module('community'));

beforeEach(inject(function ($http) {
}));
beforeEach(inject(function ($controller, $rootScope) {
}));
于 2014-12-08T15:42:11.793 回答
0

如果您的提供程序不使用全局初始化,您可以使用原始注入的提供程序并模拟它。在下面的示例中,testedProvider 是您的控制器。

var injectedProviderMock;

beforeEach(function () {
    module('myModule');
});

beforeEach(inject(function (_injected_) {
    injectedProviderMock  = mock(_injected_);
}));


var  testedProvider;
beforeEach(inject(function (_testedProvider_) {
    testedProvider = _testedProvider_;
}));

it("return value from injected provider", function () {
    injectedProviderMock.myFunc.andReturn('testvalue');
    var res = testedProvider.executeMyFuncFromInjected();
    expect(res).toBe('testvalue');
});

//mock all provider's methods
function mock(angularProviderToMock) {

    for (var i = 0; i < Object.getOwnPropertyNames(angularProviderToMock).length; i++) {
        spyOn(angularProviderToMock,Object.getOwnPropertyNames(angularProviderToMock)[i]);
    }
    return angularProviderToMock;
}
于 2015-07-08T11:14:25.313 回答