Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Injecting a mock service for an angularjs controller test

Tags:

angularjs

I'm trying to test a controller that depends on a service I built myself. I'd like to mock this service since the service talks to the DOM.

Here's my current test:

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);
        });
    });

});

My controller looks like this:

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

so it's the speedSlider I want to mock.

I had the idea to use a module I created in my test code that could provide a faked implementation of the speed slider, so I added the following to the top of the test.js file:

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

and then list that module in the beforeEach() call instead of the concrete one, but if I do that I get the following error:

Injector already created, can not register a module!

So I figure there must be a better way for me to provide a mock implementation of one of my services. Something I can perhaps use sinon.js for....

like image 938
Joseph Eames Avatar asked Jul 12 '12 19:07

Joseph Eames


People also ask

How do I inject a service in AngularJS?

There is one more way to inject dependencies in AngularJS: by using the $inject service. In doing so, we manually inject the dependencies. We can inject $scope object dependencies using the $inject service as shown in the listing below: function ProductController($scope){ $scope.

What controller do you use in Angular to mock remote data for testing?

The HttpClientTestingModule allows you to easily mock HTTP requests by providing you with the HttpTestingController service.

Which is used to inject a service into a test function?

The TestBed provides methods for creating components and services in unit tests. The TestBed methods are inject() , configureTestingModule() etc. To inject a service, we use TestBed. inject() method.

What is the injector in AngularJS used for?

$injector is used to retrieve object instances as defined by provider, instantiate types, invoke methods, and load modules.


3 Answers

Also be sure you're not trying to do this inside an inject function call:

This will throw the error:

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

This will not:

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

        inject(function(someOtherService) {
           someOtherService.doSomething();
        });
    });
like image 172
kennbrodhagen Avatar answered Sep 26 '22 03:09

kennbrodhagen


Make sure when you use module after its definition that you don't have the extra brackets. So module('TestPSPlayer') instead of module('TestPSPlayer',[]).

like image 32
Dan Doyon Avatar answered Sep 24 '22 03:09

Dan Doyon


In my case this didn't worked:

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

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

I've changed to this to make it to work:

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

beforeEach(inject(function ($http) {
}));
beforeEach(inject(function ($controller, $rootScope) {
}));
like image 26
pleerock Avatar answered Sep 26 '22 03:09

pleerock