Injecting a Mock into an Angularjs Service

Injecting a mock into an AngularJS service

You can inject mocks into your service by using $provide.

If you have the following service with a dependency that has a method called getSomething:

angular.module('myModule', [])
.factory('myService', function (myDependency) {
return {
useDependency: function () {
return myDependency.getSomething();
}
};
});

You can inject a mock version of myDependency as follows:

describe('Service: myService', function () {

var mockDependency;

beforeEach(module('myModule'));

beforeEach(function () {

mockDependency = {
getSomething: function () {
return 'mockReturnValue';
}
};

module(function ($provide) {
$provide.value('myDependency', mockDependency);
});

});

it('should return value from mock dependency', inject(function (myService) {
expect(myService.useDependency()).toBe('mockReturnValue');
}));

});

Note that because of the call to $provide.value you don't actually need to explicitly inject myDependency anywhere. It happens under the hood during the injection of myService. When setting up mockDependency here, it could just as easily be a spy.

Thanks to loyalBrown for the link to that great video.

Injecting dependent services when unit testing AngularJS services

Actually in AngularJS Dependency Injection uses the 'last wins' rule. So you can define your service in your test just after including your module and dependencies, and then when service A that you're testing will request service B using DI, AngularJS will give mocked version of service B.

This is often is done by defining new module like MyAppMocks, putting mocked services/values there and then just adding this module as dependency.

Kind of (schematically):

beforeEach(function() {
angular.module('MyAppMocks',[]).service('B', ...));
angular.module('Test',['MyApp','MyAppMocks']);
...

How to inject a mock of a service from an external file, in another service

After a lot of looking around, I found an answer by Valentyn Shybanov that explain how to do this. It is quite simple in fact. I'll leave it here for other losts souls.

Actually in AngularJS Dependency Injection uses the 'last wins' rule. So you can define your service in your test just after including your module and dependencies, and then when service A that you're testing will request service B using DI, AngularJS will give mocked version of service B.

So if you want to mock the "Views" service. You create a "BoardMocks" module that contains a "Views" service. If "BoardMocks" is included after "Board", the mocked "Views" service will be used during the tests.

See the original answer here :
Injecting dependent services when unit testing AngularJS services

How to mock a service and inject it to another service?

First create the mockedTopService, provide any function which will be needed by the test to run:

var mockedtopService = {
doSomething: function() {
return "test";
}
};

Then provide it to angular using $provide:

beforeEach(function () {
module(function ($provide) {
$provide.value('topService', mockedtopService );
});
}

In case you need to get an instance of the service via angular you can do it this way:

inject(function (topService) {
var topServiceInstance = topService;
});

Injecting mock angular service dependencies

Having figured this out, I thought I'd answer my own question. The big mistake above was using angular.module rather than angular.mock.module, that is convenience referenced as module by angular-mock. They aren't the same thing at all!

Additionally, it's enough to initialize the mock service with angular.mock.module, so long as you do it before you initialize the module under test. There's no need for this 'wrapping the modules in a third module' business as suggested in the question linked above. To wit:

describe("Test Service", function() {
var TestService, getvaluestub;

beforeEach(function() {

// create mock service
var mock = {getvalue:function(){}}

angular.module('dependencymodule',[])
.service('dependencyservice',function () {
return mock;
});

//mock the function we are stubbing, (that, in this case, returns value 4)
getvaluestub = sinon.stub(mock,'getvalue')returns(4);

//instantiate your mock service
module('dependencymodule');

//instantiate the module of the service under test,
//that depends on 'dependencyservice' mocked above
//(ie - testmodule includes the service 'testservice')
module('testmodule');

//inject your test service for testing
inject(function ($injector) {
TestService = $injector.get('testservice');
})

//tests go here.....

If the dependency module already exists, you could either still do all of the above, or you could acquire the service from the $injector, insert your spies and stubs, and >then< instantiate the service under test. It's important that the spies/stubs are set up >before< the dependent service is instantiated, or it will be instantiated without them. It looks like this:

describe("Test Service", function() {
var TestService, DependencyService, getvaluestub;

beforeEach(function() {

// these modules are specified in the application
module('dependencymodule');
module('testmodule');

inject(function ($injector) {
DependencyService = $injector.get('testservice');

getvaluestub = sinon.stub(DependencyService,'getvalue').returns(4);

OtherService = $injector.get('otherservice');
})
});

// test go here

So, there you go. Hopefully this is useful to someone who searches for 'Injecting mocks into angular services'.

Mock service injected into Angular module run block

In this case is important order.

You need load your app first

beforeEach(module("app"));

and then overwrite MyService definition.

beforeEach(
module({
"MyService": {
log: function(message) {
console.log("MyFakeService called: " + message);
}
}
})
);

Otherwise app service implementation is last registred and used.

working example is here - look to the console http://plnkr.co/edit/BYQpbY?p=preview

Unit testing angularjs - How to inject service dependency?

You have to provide your mocked service:

angular.mock.module(function($provide) {
$provide.service(„MyDatApiService“, mockMyDataApiService);
});

Injecting a mock service for an angularjs controller test

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

Injecting Mock service in AngularJS/ Jasmine

Try get the service using $injector.

beforeEach(angular.mock.inject(function($rootScope, $http, $location, $timeout, configService, $controller, $injector){
scope = $rootScope.$new();
http = $http;
location = $location;
timeout = $timeout;
service = $injector.get('configService'); //not sure the name, you may try 'ConfigService' as well.

$controller('configCtrl', {$scope: scope, $http: http, $location: location, $timeout: timeout, configService: service});
}));

Link to Demo.

Mocking a service thats provided in a component controller in a unit test

Don't you need to add 'ThirdPartyModule' in an angular.mock.module?



Related Topics



Leave a reply



Submit