Testing injected service that is a constructor function
angularjs, jasmine, testing
Solution
The reason for this is that when you run spyOn(window, 'monkEngineCreator'), the spy is put on window, not the injected value that angular uses for dependency injection.
Doing something like this should work: (untested code)
beforeEach(module('car', function($provide){
$provide.value('engine', jasmine.createSpy('engineSpy').andCallFake(function(){
return mockEngineInstance;
}));
}));
it('should init', inject(function(carCreator, engine){
var settings = {};
carCreator(settings);
expect(engine).toHaveBeenCalledWith(settings);
}));
Problem
Say I have a service like this, where a car gets an engine service injected, which is a constructor function: ``` angular.module('car', ['engine']).factory('carCreator', function( engine ) { var carCreator = function( settings ) { var engineInstance = engine( settings ); engineInstance.setMiles( settings.engine.miles ); return { brand: settings.brand; engine: engineInstance; } }; return carCreator; }); ``` How do I test both lines in the initialization logic: ``` var engineInstance = engine( settings ); engineInstance.setMiles( settings.engine.miles ) ``` 1: That `engine` is called with `settings` 2: That `engineInstance.setMiles` is called with `settings.engine.miles` This is what I'm doing right now, but with no luck: ``` describe('initialization', function() { var carCreator; var settings = { brand: 'Ford', engine: { miles: 12000 } }; var mockEngineInstance = { setMiles: function() {} }; window.mockEngineCreator = function() { return mockEngineInstance; } beforeEach(module('car', function($provide) { $provide.value('engine', mockEngineCreator ); })); beforeEach(inject(function(_carCreator_) { carCreator = _carCreator_; })); it('should init text object correctly on initialization', function() { spyOn(window, 'monkEngineCreator'); spyOn(mockEngineInstance, 'setMiles'); carCreator( settings ); expect(window.mockEngineCreator).toHaveBeenCalledWith( settings ); expect(mockEngineInstance.setMiles).toHaveBeenCalledWith( settings.engine.miles ); }); }); ``` but this test fails, saying that `window.mockEngineCreator` never was called. It seems that $provide creates a new copy of the function passed in, instead of keeping a reference to it. So, does anyone know how to setup a test that can test this correctly?