Nate
Nate

Reputation: 1750

Jasmine/AngularJS: Inject dependent service to service in unit test?

I have angular modules:

var app = angular.module("SearchUI",[]);

in it, I have a service "configService", that maintains bunch of config params:

app.provider("configService",function(){
  //stuff here
})

I have ran the jasmine unit tests in configService fineL

describe('configService',function(){

var configService,$httpBackend;


    beforeEach(module('SearchUI'));
    beforeEach(inject(function(_configService_,$injector){
        configService = _configService_;    
        $httpBackend = $injector.get("$httpBackend");

    }));

    it('should have default values for configService', function(){
        expect(configService.getDefaultSearch()).toEqual(['abstract','title','keyword','keywordplus'
    ]);
    });

//other stuff

all tests pass fine.

however, I am not understanding how to maintain that injection in another service:

i.e in my application:

app.service("SearchService",function($http,$log,configService,$q){
    //stuff
    search_params = configService.getDefaultSearch();

})

my spec:

describe('SearchService',function(){
    var searchService,configService;

    beforeEach(module('SearchUI'));
    beforeEach(inject(function(_configService_,_SearchService_){
        configService = _configService_;    
        searchService = _SearchService_;

    }));


    it('SearchService should return results', function(){
        var waiting = searchService.SimpleSearch("card","wos",0);


//other stuff

the spec fails because in simplesearch function requires this:

search_params = configService.getDefaultSearch(); //get the default search parameters       

my question is, how do I inject the required service in to the ANOTHER service?

Upvotes: 8

Views: 6108

Answers (2)

olivier
olivier

Reputation: 11

configService and SearchService are init in module app but not in module SearchUI. Replace "beforeEach(module('SearchUI'));" by "beforeEach(module('myapp'));"

Upvotes: 1

Brocco
Brocco

Reputation: 64843

Services are simply JavaScript classes and you can create an instance of them without using angular's inject mechanism to facilitate your dependency injection. Instead you can simply create a new instance of the class yourself while supplying the parameters which are required.

Currently you are creating your service via an inline function:

app.service("SearchService",function($http,$log,configService,$q){...

Instead of that by making a small adjustment which will separate out the declaration of the service from its injection into the angular module. Doing so will allow you to gain access from your test to the service class.

function SearchService($http, configService){...

app.service("SearchService", SearchService);

From your test you suite you can prepare your injectables in your beforeEach preprocessor:

describe('configService',function(){

    var configService, httpBackend;
    beforeEach(module('SearchUI'));
    beforeEach(inject(function($httpBackend){
        httpBackend = "$httpBackend";
        configService = jasmine.createSpyObj('configService', ['getDefaultSearch']);
    }));

    /* helper method that I create to only have one place where the service is created 
    If I add a new param/dependency then I only have to change the construction once */
    function createService(){
        return new SearchService(httpBackend, configService);
    }
});

The main reason for taking this approach to testing (controlling the dependency injection manually rather than relying on angular's implementation) is to have full control and to truly isolate the item I am trying to test.

Upvotes: 5

Related Questions