Unit testing
with
Karma and Jasmine
Contents
- Building and running unit tests
- Basic blocks and structures
- Loading fixtures
- Unit testing services
- Unit testing directives
- Unit testing controllers
- Mocking back-end responses
- Spies
- Links
Building and running unit tests
$ gulp build
Build project:
$ gulp test
Run tests:
Run once:
$ gulp test-dev
Watch changes:
Basic blocks and structures
- describe()
- module()
- beforeEach()
- inject()
- it()
- expect()
There are six most commonly used structures and blocks:
Grouping tests by topic:
describe(`Name of group or a module`, () => {
...
});
Importing AngularJS modules and dependencies:
module('app.settings');
Executing actions before each test:
beforeEach(() => {
module('app.service');
});
Injecting services for further use in tests (underscore
annotation):
let $rootScope;
let customService;
inject((_$rootScope_, _customService_) => {
$rootScope = _$rootScope_;
customService = _customService_;
});
Test case blocks:
it(`Should show a test block example.`, () => {
...
});
Assertion of a value:
it(`Should return 'Hello world'`, () => {
let ahoy = 'Hello world';
expect(ahoy).toBe('Hello world'); // will pass
});
Available assertion matchers:
.toBe()
.toBeCloseTo()
.toBeDefined()
.toBeFalsy()
.toBeGreaterThan()
.toBeGreaterThanOrEqual()
.toBeLessThan()
.toBeLessThanOrEqual()
.toBeNaN()
.toBeNull()
.toBeTruthy()
.toBeUndefined()
.toContain()
.toEqual()
.toHaveBeenCalled()
.toHaveBeenCalledTimes()
.toHaveBeenCalledWith()
.toMatch()
.toThrow()
.toThrowError()
Example test case:
describe('Reverse filter', () => {
let $filter;
const timezones = [
'(GMT-11) Niue Time',
'(GMT+0) Azores Summer Time',
'(GMT+5) French Southern & Antarctic Lands Time',
];
beforeEach(() => {
module('app.filters');
inject((_$filter_) => {
$filter = _$filter_;
});
});
it('Wrong string value passed. Should return string', () => {
expect($filter('timezoneLabel')('Hello world')).toEqual('Hello world');
});
it('Proper value passed. Negative offset. Should return GMT +0', () => {
expect($filter('timezoneLabel')(timezones[0])).toEqual('GMT -11');
});
it('Proper value passed. Zero offset. Should return GMT +0', () => {
expect($filter('timezoneLabel')(timezones[1])).toEqual('GMT +0');
});
it('Proper value passed. Positive offset. Should return GMT +5', () => {
expect($filter('timezoneLabel')(timezones[2])).toEqual('GMT +5');
});
});
Fixtures
Importing fixtures:
fixture.setBase('test/mocks');
- (optional) set mocks base path
let mock = fixture.load('mock_file.json');
- load fixture from a file
Testing Services
Service test example:
Refer to menu.srv.spec.js
Testing directives
$scope = rootScope.$new(); // also a simple empty object will do
let element = $compile('<div custom-directive')($scope);
- Compile directive before each test
it(`Should return 'Hello world'`, () => {
let scope = $rootScope.$new();
scope.value = '';
const element = $compile('<div custom-directive="value"></div>')(scope);
expect(element.text()).toBe('');
scope.value = 'Hello world';
$rootScope.$digest();
expect(element.text()).toBe('Hello world');
});
- Run $rootScope.$digest() to apply scope changes
Testing Controllers
$scope = rootScope.$new(); // also a simple empty object will do
let CustomController = $controller('CustomController', { $scope });
- get controller with $controller service before each test
am.controller('CustomController', function($scope, dependencyExample) => {});
const dependencyExample = { customMethod: (data) => data || [] };
let CustomController = $controller('CustomController', { $scope, dependencyExample });
- mock dependencies if you need it
Mocking Back-end responses
$httpBackend.expectGET('/user').respond(fixture.load('user.json'));
- expect
// will return a fixture
$httpBackend.when('/user').respond(fixture.load('user.json'));
// will return success response
$httpBackend.when('/user').respond(200);
// will return error response
$httpBackend.when('/user').respond(500);
- when
$httpBackend service
Spies
let rabbit = {
jump: (direction) => console.log(`Jump ${direction}!`);
}
spyOn(rabbit, 'jump');
rabbit.jump('up');
expect(rabbit.jump).toHaveBeenCalled();
expect(rabbit.jump).toHaveBeenCalledTimes(1);
expect(rabbit.jump).toHaveBeenCalledWith('up');
- used to spy on methods and functions
- Karma test-runner api - https://karma-runner.github.io/0.13/dev/public-api.html
- Jasmine documention - http://jasmine.github.io/edge/introduction.html
Links
Unit testing AngularJS with Karma and Jasmine
By Oleksandr Hutsulyak
Unit testing AngularJS with Karma and Jasmine
- 374