Www.luxoft.com AngularJS Forms & validation. AngularJS form example First.
AngularJS Unit Testing
-
Upload
prince-norin -
Category
Technology
-
view
192 -
download
0
Transcript of AngularJS Unit Testing
ANGULARJS UNIT TESTING
Hor Norin7 November 2016
Objective & Goals• Why unit test?• Basic Setup• Jasmine• AngularJS Testing• Mocking & Stubbing• Best Practices
WHY UNIT TESTING?
Why Unit Testing?• Reduce bug• Improve code quality• Good documentation• Defend against other programmers• Make you feel confident
BASIC SETUP
Tools You Need• Node.js• Karma• Jasmine• Angular Mock• Browser
Package.json{ "name": "jasmine", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "karma start" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "angular": "^1.5.8" }, "devDependencies": { "angular-mocks": "^1.5.8", "jasmine-core": "^2.5.2", "karma": "^1.3.0", "karma-jasmine": "^1.0.2", "karma-phantomjs-launcher": "^1.0.2" }}
Setup Karma• npm install karma-cli –g• karma init• karma start
Configuration Options• frameworks• files• exclude• browsers• basePath• preprocessors• singleRun• autoWatch
JASMINE
Functions• Suite: describe• Spec: it• Setup: beforeEach• Teardown: afterEach• Expectation: expect
Matchersexpect(array).toContain(member);expect(fn).toThrow(string);expect(fn).toThrowError(string);expect(instance).toBe(instance);expect(mixed).toBeDefined();expect(mixed).toBeFalsy();expect(mixed).toBeNull();expect(mixed).toBeTruthy();expect(mixed).toBeUndefined();expect(mixed).toEqual(mixed);expect(mixed).toMatch(pattern);expect(number).toBeCloseTo(number, decimalPlaces);expect(number).toBeGreaterThan(number);expect(number).toBeLessThan(number);expect(number).toBeNaN();expect(spy).toHaveBeenCalled();expect(spy).toHaveBeenCalledTimes(number);expect(spy).toHaveBeenCalledWith(...arguments);
Custom Matcher• Use addMatchers• Factory object with factory function• Return object with compare function• Result of compare must contains pass and message property
Custom MatcherExample:
ANGULARJS TESTING
Loading Moduledescribe('App', function() { beforeEach(module(’App'));
it('1 + 1 should equal 2', function() { // some expectations });});
Controllerdescribe('SomeController', function() { var $scope, $controller;
beforeEach(function() { module('App'); inject(function($rootScope, _$controller_) { $scope = $rootScope.$new(); $controller = _$controller_; }); });
it('expect someModel to equal someValue', function() { var ctrl = $controller('SomeController', { $scope: $scope });
// $scope style expect($scope.someModel).toEqual(someValue); // controllerAs style expect(ctrl.someModel).toEqual(someValue); });});
Componentdescribe('SomeComponent', function() { var $componentController, $scope;
beforeEach(function() { module('App');
inject(function($rootScope, _$componentController_) { $scope = $rootScope.$new(); $componentController = _$componentController_; }); });
it('expect someModel to equal someValue', function() { var component = $componentController('SomeComponent', null); expect(component.someModel).toEqual(someValue); });});
Directivedescribe('Greeting', function() { var $scope, $compile;
beforeEach(function() { module('App'); inject(function($rootScope, _$compile_) { $scope = $rootScope.$new(); $compile = _$compile_; }); });
it('should contain greeting text', function() { var el = $compile('<greeting name="Norin"></greeting>')($scope); // fire all watchers so that expression // like {{ 1 + 1 }} will be evaluate $scope.$digest(); expect(el.html()).toContain('Hello Norin'); });});
Servicedescribe('Calculator', function() { var $scope, calculator;
beforeEach(function() { module('App'); inject(function($rootScope, _calculator_) { $scope = $rootScope.$new(); calculator = _calculator_; }); });
it('should return sum of two value', function() { expect(calculator.sum(10, 20)).toEqual(30); });});
Filterdescribe('Reverse', function() { var $scope, $filter;
beforeEach(function() { module('App'); inject(function($rootScope, _$filter_) { $scope = $rootScope.$new(); $filter = _$filter_; }); });
it('should make text reverse', function() { var reverseText = $filter('reverse')('Hello'); expect(reverseText).toEqual('olleH'); });});
MOCKING & STUBBING
Stub Object MethodspyOn(someObj, 'someMethod').and.returnValue(3);expect(someObj.someMethod()).toEqual(3);
spyOn(someObj, 'someMethod').and.callFake(function() { return 10;});expect(someObj.someMethod()).toEqual(10);
Message Expectationvar norin = { info: function() { return 'Name: Norin, Gender: Male'; }};
function greeting(person) { console.log(person.info());}
spyOn(norin, 'info');greeting(norin);
expect(norin.info).toHaveBeenCalled();expect(norin.info.calls.count()).toBe(1);
Mock API Request$httpBackend.when('GET', 'http://example.com/search?q=product1').respond(200, [1,2]);
var products = null;expect(products).toBeNull();productService.search('product1') .then(function(res) { products = res.data; }) .catch(function(error) { products = []; });
$httpBackend.flush();expect(products).not.toBeNull();expect(products.length).toBe(2);
BEST PRACTICES
Things to Be Done• Test case should be done in isolation• Make use of custom matcher• Reactor out code if need
Things to Avoid• Directly use global variable & function• Nest describe block too deep• DRY too much makes it less readable
RESOURCES & REFERENCES
Resources & References• https://jasmine.github.io/2.0/introduction• https://docs.angularjs.org/api/ngMock
Further Reading• https://docs.angularjs.org/guide/e2e-testing• https://github.com/angular/protractor