Taunting my own service in unit test

I have a service that accepts some of my other services as a dependency. How can I mock unit test?

myApp.factory('serviceToTest', ['serviceDependency', function(serviceDependency) { return function(args) { return cond(args) ? serviceDependency() : somethingElse(); }; } ]); 

In the example above, I want to mock serviceDependency to verify that it was called. How can i do this?

I could just do the following in a 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 is great for a test that needs a layout, but then affects the state of all other tests, which is obviously a problem.

+6
source share
3 answers

Here is an example from my open source project: https://github.com/lucassus/mongo_browser/blob/f1faf1b89a9fc33ef4bc4eced386c30bda029efa/spec/javascripts/app/services_spec.js.coffee#L25 (sorry c crypt). As a rule, inside the specification it is necessary to create and include a new module that redefines this service.

+3
source

If I understand you correctly, you want to test a service that depends on another service, and make fun of the dependency for each test. If yes, let's say that we have a car that has a dependency on 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 the car and make fun of the engine. There are two ways to do this: either by defining a new module in which we could override the 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'); })); }); 

The desktop is here: http://plnkr.co/edit/ueXIzk?p=preview

A slightly simpler alternative, relaying the 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

Another alternative is to use Jasmine spying:

 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

+11
source

I had the same problem that was trying to embed a service layout in another provider.

This post by Pete Bacon Darwin set me on the right path: https://groups.google.com/d/msg/angular/TvBknXnjRyQ/xtCDkJyqp6MJ

Here is an example application:

 angular.module('MyApplication', []) .service('MyServiceDependency', [function(){ // Behaviour here. }]) .factory('MyFactory', ['MyServiceDependency', function(MyServiceDependency){ // Behaviour here. }]); 

We want to make fun of MyServiceDependency to test the behavior of MyFactory , so we write our tests as follows:

 describe(function(){ var MyFactory; beforeEach(function(){ // 1. Include your application module for testing. angular.mock.module('MyApplication'); // 2. Define a new module. // 3. Define a provider with the same name as the one you want to mock (in our case we want to mock 'MyServiceDependency'. angular.module('MyAppMock', []) .service('MyServiceDependency', function(){ // Define you mock behaviour here. }); // 4. Include your new mock module - this will override the providers from your original module. angular.mock.module('MyAppMock'); // 5. Get an instance of the provider you want to test. inject(function($injector){ // `MyFactory` will receive the mocked version of `MyServiceDependency`. MyFactory = $injector.get('MyFactory'); }); }); it('MyFactory does something special', function(){ MyFactory(); // Test your provider. }); }); 
+7
source

All Articles