简体   繁体   中英

Spyon provider during config phase in angular.js application

I am writing unit tests for an Angular.js application (with karma and jasmine), and I want to test a certain behavior in the CONFIG phase of a module. I would like to confirm that a certain function of a PROVIDER is being called. I thought I could do this with a spy on the provider's method, but gaining access to the provider before the "expect" has proven rather tricky. Here is some example code:

Module Code (being tested)

var myApp = angular.module('myApp', ['restangular']);
myApp.config(['RestangularProvider', function (RestangularProvider) {
    RestangularProvider.setBaseUrl('http://someurl:someport/');
}]);

I've tried various solutions to get a reference to the RestangularProvider and apply a spy to it, and all failed. The closest I was able to get was the code below:

Unit Test Code

describe("Test if setBaseUrl was called", function () {
    var RestangularProvider;
    beforeEach(module('myApp', function(_RestangularProvider_) {
        RestangularProvider = _RestangularProvider_;
        spyOn(RestangularProvider, "setBaseUrl").and.callThrough();
    }));

    it("should call setBaseUrl.", function() {
        expect(RestangularProvider.setBaseUrl).toHaveBeenCalled();
    });
});

I do actually get the reference to the RestangularProvider, but the "config" function of the module gets called before that, so I think the spy doesn't get set-up.

I did find a post where the author solved a similar situation with a "work around" by testing the configured "service" instead of testing the actual call to the provider's method. In the example above, I would test the Restangular.configuration.baseUrl in my expect instead of testing the actual call to the provider's setBaseUrl method, but this seemed like it would not be adequate in certain situations.

I am rather new to Angular.js so this may simply be a case of being totally clueless as to the whole "testing config phase", so if that's the case, please feel free to set me straight :]

Any suggestions, critiques or pointers?

I finally solved the problem by separating out the module, whose provider I wanted to spy on, into a diferent "beforeEach" block. The altered code is below, but I still would appreciate any comments as to the whole idea of whether or not this is actually an "adequate test".

describe("Test if setBaseUrl was called", function () {
    var RestangularProvider;
    //Setup the spy.
    beforeEach(function () {

      module("restangular", function(_RestangularProvider_) {
        RestangularProvider = _RestangularProvider_;
        spyOn(_RestangularProvider_, 'setBaseUrl').and.callThrough();
      });
    });

    beforeEach(module('myApp'));

    it("should call setBaseUrl.", function() {
        expect(RestangularProvider.setBaseUrl).toHaveBeenCalled();
    });
});

As described by OP above, you do need to get the provider before calling the module you want to test.
However, there's no need to separate it in two beforeEach blocks. You also must call inject() function (even if you have nothing to inject) at the end of the beforeEach block.

describe('Test if setBaseUrl was called', function () {
  var RestangularProvider;
  //Setup the spy.
  beforeEach(function () {

    module('restangular', function(_RestangularProvider_) {
      RestangularProvider = _RestangularProvider_;
      spyOn(_RestangularProvider_, 'setBaseUrl').and.callThrough();
    });

    module('myApp');

    inject();
  });

  it('should call setBaseUrl.', function() {
    expect(RestangularProvider.setBaseUrl).toHaveBeenCalled();
  });
});

Source: http://java.dzone.com/articles/unit-testing-config-and-run

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM