25

I'm trying to learn how to write unit tests for AngularJS. I started at the beginning, with

angular.module( ... ).config( ... )

I wanna test what's inside config. Here's how the relevant portions look like:

angular.module('ogApp', ['ngCookies','ui.router','ogControllers','ogServices','ogDirectives','ogMetricsData'])

.config([
  '$stateProvider', '$locationProvider',
  function ($stateProvider, $locationProvider) {
    $stateProvider.
      state('login', {
        templateUrl: 'connect.html'
      }).state('addViews', {
        templateUrl: 'add-views.html'
      }).state('dashboard', {
        templateUrl: 'dashboard.html'
      });
    $locationProvider.
      html5Mode(true).
      hashPrefix('!');
  }
]);

I'm thinking the easiest way to test this code is to inject mocks for $stateProvider and $locationProvider. Then execute the config phase. After that, assert how $stateProvider and $locationProvider should look like.

If my thinking is right, my problem then is, I have no idea how to inject those mocks into the module and execute its config phase from a test.

Could you show me how to test this code?

3
  • did you find a suitable solution to handle this?? Commented Jul 24, 2014 at 13:12
  • @Brune Nope. But there's a new answer below that I haven't looked into. Commented Jul 24, 2014 at 13:31
  • I am facing same issue. How to inject config section? Commented Oct 14, 2021 at 17:31

3 Answers 3

11

Here's how to access your provider for unit testing:

describe('yourProvider', function () {
    var provider;

    // Get the provider
    beforeEach(module('app', function (yourProvider) {
        // This callback is only called during instantiation
        provider = yourProvider;
    });

    // Kick off the above function
    beforeEach(inject(function () {}));

    it('does its thing', function () {
        expect(provider.someMethod()).toEqual('your results');
    });
});

I have not yet figured out a really simple way to inject a mock, but you can easily spy on methods and that's close enough. If you need a mock returned from the dependency provider's .$get() method you can do that with another spy as well. This example illustrates returning a mock and setting up an additional spy.

describe('yourProvider', function () {
    var dependency, mock, provider;

    beforeEach(module('app', function (dependencyProvider) {
        dependency = dependencyProvider;
        mock = jasmine.createSpyObj('dependency', [
            'methodsGoHere'
        ]);
        spyOn(dependency, 'methodName');
        spyOn(dependency, '$get').andReturn(mock);
    }, function (yourProvider) {
        provider = yourProvider;
    });

    beforeEach(inject(function () {}));

    it('does its thing', function () {
        expect(provider.someMethod()).toEqual('your results');
        expect(dependency.methodName).toHaveBeenCalled();
    });

    it('returns the mock from $get', function () {
        expect(dependency.$get).toBe(mock);
    });
});
Sign up to request clarification or add additional context in comments.

Comments

0

You can use Jasmine's createSpy and createSpyObj to create the mock services, and angular-mocks.js to inject them.

More instructions on injecting mocks here: Injecting a mock into an AngularJS service

In this test I wrote for a directive of mine you can see the following:

  • Line 9 Include angular-mock from the google cdn
  • Line 19 & 20 Create a fake rootScope object
  • Line 21 & 22 Create a fake q service
  • Line 42 Setup the provider to inject the fakes into the service
  • Line 48 Instantiate the service that has the fakes (this service is injected into the directive under test)
  • Line 53 Call the method being tested
  • Line 55 - 59 Assert on the state of the fakes

3 Comments

Jason, The last link is broken. Also, my challenge is not in injecting mocked dependencies in general. It's just with injecting mocked providers to the config block.
MK, were you able to find a solution for the same? I am stuck with same issue and not able to test the directive.
@PriyabratNanda Nope. But there's a new answer below that I haven't looked into.
-1

I would create a factory that points to a function... that function is then also called within the config function. That way you can unit test the factory:

angular.module('ogApp', ['ngCookies','ui.router','ogControllers','ogServices','ogDirectives','ogMetricsData']);

// Configuration factory for unit testing
angular.module('ogApp')
.factory('configuration', configuration);

configuration.$inject = ['$stateProvider', '$locationProvider'];

function configuration($stateProvider, $locationProvider) {
  return {
    applyConfig: function () {
      $stateProvider.
        state('login', {
          templateUrl: 'connect.html'
        }).state('addViews', {
          templateUrl: 'add-views.html'
        }).state('dashboard', {
          templateUrl: 'dashboard.html'
        });
      $locationProvider.
        html5Mode(true).
        hashPrefix('!');
    };
}

// Call above configuration function from Angular's config phase
angular.module('ogApp')
.config([
  '$stateProvider', '$locationProvider',
  function ($stateProvider, $locationProvider) {
    var config = configuration($stateProvider, $locationProvider);
    config.applyConfig();
  }
]);

You can unit test the configuration factory and inject mocks just like you would with any other factory.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.