Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Injecting mock angular service dependencies

Tags:

angularjs

I have a service, 'Inputs', defined in module 'Puts', that depends on a second service, 'InputCreator'. I need to stub the InputCreator service in order to test the Inputs service.

As I understand the answer here, I should create a module containing my stub service, then create a new 'Test' module, specifying the module under test and then the stub module as dependencies. And then pull the service from the injector. Like so:

beforeEach(function() {

  angular.module.('Puts'); // contains the service 'Inputs'

  angular.module('Mocks',[])
    .service('InputCreator',function(){
      var mockInputs = {
        //stubbed behaviour goes here
      };
      return mockInputs;
    });
  });

  angular.module('Test',['Puts', 'Mocks'];

  inject(function($injector){
    Inputs = $injector.get('Inputs');
  });
});

However, the injector function responds with 'unknown InputsProvider <- Inputs'.

Where have I gone astray?

Thanks!

like image 938
Jon Biz Avatar asked Sep 10 '13 23:09

Jon Biz


1 Answers

Having figured this out, I thought I'd answer my own question. The big mistake above was using angular.module rather than angular.mock.module, that is convenience referenced as module by angular-mock. They aren't the same thing at all!

Additionally, it's enough to initialize the mock service with angular.mock.module, so long as you do it before you initialize the module under test. There's no need for this 'wrapping the modules in a third module' business as suggested in the question linked above. To wit:

describe("Test Service", function() {
  var TestService, getvaluestub;

  beforeEach(function() {

    // create mock service
    var mock = {getvalue:function(){}}

    angular.module('dependencymodule',[])
      .service('dependencyservice',function () {
        return mock;
      });

    //mock the function we are stubbing, (that, in this case, returns value 4)
    getvaluestub = sinon.stub(mock,'getvalue')returns(4);

    //instantiate your mock service
    module('dependencymodule');

    //instantiate the module of the service under test, 
    //that depends on 'dependencyservice' mocked above 
    //(ie - testmodule includes the     service 'testservice')
    module('testmodule');

    //inject your test service for testing
    inject(function ($injector) {
        TestService = $injector.get('testservice');
    })

  //tests go here.....

If the dependency module already exists, you could either still do all of the above, or you could acquire the service from the $injector, insert your spies and stubs, and >then< instantiate the service under test. It's important that the spies/stubs are set up >before< the dependent service is instantiated, or it will be instantiated without them. It looks like this:

describe("Test Service", function() {
  var TestService, DependencyService, getvaluestub;

  beforeEach(function() {

    // these modules are specified in the application
    module('dependencymodule');
    module('testmodule');

    inject(function ($injector) {
      DependencyService = $injector.get('testservice');

      getvaluestub = sinon.stub(DependencyService,'getvalue').returns(4);

      OtherService = $injector.get('otherservice');
    })
  });

// test go here

So, there you go. Hopefully this is useful to someone who searches for 'Injecting mocks into angular services'.

like image 72
Jon Biz Avatar answered Oct 25 '22 05:10

Jon Biz