Reputation: 7019
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?
Upvotes: 25
Views: 10026
Reputation: 2722
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.
Upvotes: -1
Reputation: 853
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);
});
});
Upvotes: 11
Reputation: 15931
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:
Upvotes: 0