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?
Unit tests are easy to write and faster in execution. In unit testing, we don't test the functionality of an app hence low confidence. AngularJS consists of various building blocks like services, components, directives, etc. For each of them, we need to write separate test cases.
AngularJS is written with testability in mind, but it still requires that you do the right thing. We tried to make the right thing easy, but if you ignore these guidelines you may end up with an untestable application.
Angular Unit testing is the process of testing small and isolated pieces of code in your Angular application. This provides an added advantage to the users in the sense that they can add any new features without breaking any other part of their application.
Configuration block is executed during bootstrap process which is before any controller or directive code. Once bootstrap is done, configuration blocks can't execute. Once boostrap is done, providers aren't injectable any more. So property or method on providers can't be called after boostrap phase.
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); }); });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With