I\'m testing service A, but service A depends on service B (i.e. service B is injected into service A).
I\'ve seen this question but my case is a bit different becau
I find the simplest method is just to inject service B and mock it. e.g. Service car depends on service Engine. Now we need to mock Engine when testing Car:
describe('Testing a car', function() {
var testEngine;
beforeEach(module('plunker'));
beforeEach(inject(function(engine){
testEngine = engine;
}));
it('should drive slow with a slow engine', inject(function(car) {
spyOn(testEngine, 'speed').andReturn('slow');
expect(car.drive()).toEqual('Driving: slow');
}));
});
Reference: https://github.com/angular/angular.js/issues/1635
This is what worked for me. The key is defining a real module to be mocked. Calling angular.mock.module makes the real module mockable and allows things to be connected.
beforeEach( ->
@weather_service_url = '/weather_service_url'
@weather_provider_url = '/weather_provider_url'
@weather_provider_image = "test.jpeg"
@http_ret = 'http_works'
module = angular.module('mockModule',[])
module.value('weather_service_url', @weather_service_url)
module.value('weather_provider_url', @weather_provider_url)
module.value('weather_provider_image', @weather_provider_image)
module.service('weather_bug_service', services.WeatherBugService)
angular.mock.module('mockModule')
inject( ($httpBackend,weather_bug_service) =>
@$httpBackend = $httpBackend
@$httpBackend.when('GET', @weather_service_url).respond(@http_ret)
@subject = weather_bug_service
)
)
The Valentyn solution worked for me, but there is another alternative.
beforeEach(function () {
angular.mock.module("moduleThatContainsServiceA", function ($provide) {
$provide.value('B', ...);
});
});
Then when AngularJS service A request the Service B by Dependency Injection, your mock of Service B will be provided instead of the Service B from moduleThatContainsServiceA.
This way you don't need to create an additional angular module just to mock a Service.
I was doing this in CoffeeScript and found an extra gotcha. (Also, I found the code on this page to be confusingly terse.) Here's a complete working example:
describe 'serviceA', ->
mockServiceB = {}
beforeEach module 'myApp' # (or just 'myApp.services')
beforeEach ->
angular.mock.module ($provide) ->
$provide.value 'serviceB', mockServiceB
null
serviceA = null
beforeEach inject ($injector) ->
serviceA = $injector.get 'serviceA'
it 'should work', ->
expect( true ).toBe( true )
#serviceA.doStuff()
Without explicitly returning null after $provide.value
, I kept getting Error: Argument 'fn' is not a function, got Object
. I found the answer in this Google Groups thread.
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']);
...