Skip to content

wejendorp/angular-unittest

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Angular unittest

These tests are meant as a how to do the most basic unit tests of different angular components. Either where the angular documentation falls short, or for commonly used non-standard libraries.

If you have not read the official unit testing guide, start here.

Disclaimer: This is a work in progress, and is used as my personal playground for figuring out how to do different kinds of testing. I hope you'll find some of it useful, and would appreciate any and all feedback.

Instructions

This project uses the karma test runner and the Jasmine testing framework. All samples should be equally applicable to your chosen testing setup.

Dependencies are fetched via npm(1) and bower.

$ npm install
$ npm test

The npm test command is configured in package.json and is an alias for bower install followed by karma start karma.conf.

Controllers with forms

There is little documentation available on unit testing controllers that depend on a $formController. You depend on FormControllers whenever you access a form on the scope.

The only real clue on how to test forms, is found in the angular form directive test, e.g. L41-L44.

Solution: $compile your template, passing in the controller scope to initialize the scope.formName references before handing it to your controller. Remember to run scope.$digest() to intialize the state.

This has the added benefit of letting you access the element that is returned when compiling the template, and getting template behavior into your tests.

beforeEach(function() {
  this.scope    = $rootScope.$new();
  var template = $templateCache.get('myTemplate');
  this.element  = $compile(template)(this.scope);  
  this.scope.$digest();
});

// your scope is now tied to your template
it('is tied to form', function() {
  expect(this.scope.myForm.$valid).toBe(true);
  // Change some stuff here
  this.scope.model = 'angular';

  this.scope.$digest();
  /// Validate changes here

  expect(this.scope.myForm.$valid).toBe(true);
});

For a simple example as a full jasmine test, see the sample formControllerSpec.

See also

Application States (ui-router)

Urls

$state.href will return the url of any state for easy verification.

it('should respond to URL', function() {
  expect($state.href('myState', { id: 1 })).toEqual('#/state/1');
});

Resolves

A state is only as good as its data. How do we check if it resolves the expected data? We mock out the services that are expected to be called, and check that

module('StateApp', function($provide) {
  $provide.value('myService', myServiceMock = {});
});

Gotcha: if you need to set up a modules .config step, you can do so in the module functions' callback. Here we use the step to mock out a service.

it('should resolve data', function() {
  myServiceMock.findAll = jasmine.createSpy('findAll').andReturn('findAll');

  $state.go(state, { id: 1 });
  $rootScope.$digest();
  expect($state.current.name).toBe(state);

  // Call invoke to inject dependencies and run function
  expect($injector.invoke($state.current.resolve.data)).toBe('findAll');
});

For a simple example as a full jasmine test, see the sample appStateSpec.

Nested states

expect($state.$current.locals.globals.data).toBe('findAll');

Note the difference. The method used above for invoke($state.current.resolve.data) will only check resolutions defined on the chosen state. For nested states, the resolved data is available as $state.$current.locals.globals, which includes resolutions from parent states.

  • Use invoke to get the isolated resolutions for the chosen state.
  • Use $state.$current.locals.globals to get all resolutions of this state and its parents.

See also

Thanks to Philip Chen for the answer to state mocking on StackOverflow.

About

Unit testing stubs for angular components

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published