I have a service that takes several of my other services as a dependency. How can I mock it out for a unit test?
myApp.factory('serviceToTest',
['serviceDependency',
function(serviceDependency) {
return function(args) {
return cond(args) ? serviceDependency() : somethingElse();
};
}
]);
In the above example, I want to mock out serviceDependency
so I can verify that it was called. How can I do that?
I could just do the following in the test:
describe("Services", function() {
describe('serviceToTest', function() {
myApp.factory('serviceDependency', function() {
var timesCalled = 0;
return function() {
return timesCalled++;
}
});
it('should do foo', inject(function(serviceToTest, serviceDependency) {
serviceToTest(["foo", "bar", "baz"]);
expect(serviceDependency()).to.equal(1);
});
});
});
This works fine for the test that needs the mock, but it then affects the state of all the other tests that follow, which is obviously a problem.
If I understand you correctly you want to test a service that depends on another service and mock a dependency for each test. If so, let's say that we've got a car
that has a dependency on an engine
:
var app = angular.module('plunker', [])
.factory('car', function(engine) {
return {
drive : function() {
return 'Driving: ' + engine.speed();
}
}
})
.value('engine', {
speed : function() {
return 'fast';
}
});
Then you want to test a car and mock an engine. There are 2 ways of doing so: either by defining a new module in which we could redefine an engine:
describe('Testing a car', function() {
var testEngine;
beforeEach(function(){
testEngine = {};
angular.module('test', ['plunker']).value('engine', testEngine);
module('test');
});
it('should drive slow with a slow engine', inject(function(car) {
testEngine.speed = function() {
return 'slow';
};
expect(car.drive()).toEqual('Driving: slow');
}));
});
A working plunk here: http://plnkr.co/edit/ueXIzk?p=preview
A bit simpler alternative, relaying on dynamic nature of JavaScript:
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) {
testEngine.speed = function() {
return 'slow';
};
expect(car.drive()).toEqual('Driving: slow');
}));
});
http://plnkr.co/edit/tlHnsJ?p=preview
Yet another alternative is to use a Jasmine's spy:
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');
}));
});
http://plnkr.co/edit/K4jczI?p=preview
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With