[Unit Testing] AngularJS Unit Testing - Karma
2016-03-06 18:14
579 查看
Install Karam:
Init Karam:
First test:
1. Add test file to the karma.conf.js:
2. Add test file:
Of course, it will failed.
Then we make it pass:
Testing with AngularJS
Install angular-mocks:
Include the angular.js and angular-mocks.js file before the test file:
Write the test file:
Now, "4" is not "5", then it will failed, switch to "4" to make it pass.
[b]Testing Directive[/b]:
Underscore notation: The use of the underscore notation (e.g.:
2. Add config to karma.config.js:
3. Add html into beforeEach:
Testing Directive Scope:
1. Check after a click event, scope value changed:
2. Isolated scope testing:
You can no long use "element.scope()" or "$scope", you should use "element.isolateScope()".
[b]Testing Directive Scope Binding[/b]:
Tow ways binding:
Testing Speed:
Using ddescriber plugin to speed up unit testing.
Install the plugin "ddscriber for jasmine". Ctrl+Shift+D, to open the dailog. In the dialog you can choose which test to be included or not.
The code is modfied as:
ddscribe / iit -- include
xdscribe / xit -- exclude
Testing Service:
Testing service, you need to inject the service into beforeEach.
This testing case is test whenever use a service to get a name we will append " Smith" to the end.
Testing Controller:
Testing controller, you need to inject the $controller into beforeEach. And get ctrl instence by using:
npm install -g karma
npm install -g karma-cli
Init Karam:
karma init
First test:
1. Add test file to the karma.conf.js:
// list of files / patterns to load in the browser files: [ 'test/hello.js' ],
2. Add test file:
describe('First Unit testing with Karma', function() { it('sholud work', function() { expect(true).toBe(false); }) })
Of course, it will failed.
Then we make it pass:
describe('First Unit testing with Karma', function() { it('sholud work', function() { expect(true).toBe(true); }) })
Testing with AngularJS
Install angular-mocks:
npm install angular-mocks
Include the angular.js and angular-mocks.js file before the test file:
// list of files / patterns to load in the browser files: [ 'test/hello.js', 'bower_components/angular/angular.js', 'node_modules/angular-mocks/angular-mocks.js', 'test/anuglarjs.js' ],
Write the test file:
describe('Testing with AngularJS', function() { //Want $scope and element can be used globally var $scope, element; //We need to inject $compile, $rootScope beforeEach(inject(function($compile, $rootScope) { $scope = $rootScope; //create an 'angular element' element = angular.element("<div>{{2+2}}</div>"); //then compile it to real angular element //also it requires link function and scope element = $compile(element)($rootScope); })); it('should equals to 4', function() { //make sure to $digest() it to get the change $scope.$digest(); expect(element.html()).toBe("5"); // change to "4" to make it pass }) })
Now, "4" is not "5", then it will failed, switch to "4" to make it pass.
[b]Testing Directive[/b]:
.directive('aGreatEye', function () { return { restrict: 'E', replace: true, //Important to add replace: true, otherwise, it would be <h1 class="ng-binding">...</h1>" template: '<h1>lidless, wreathed in flame, {{1 + 1}} times</h1>' }; });
describe('Testing directive', function() { var $scope, $compile, element; beforeEach(module('app')); beforeEach(inject(function(_$compile_, _$rootScope_) { $compile = _$compile_; $scope = _$rootScope_; })); it("Replaces the element with the appropriate content", function() { element = $compile('<a-great-eye></a-great-eye>')($scope); $scope.$digest(); expect(element.html()).toBe('lidless, wreathed in flame, 2 times'); }) });
Underscore notation: The use of the underscore notation (e.g.:
_$rootScope_) is a convention wide spread in AngularJS community to keep the variable names clean in your tests. That's why the
$injectorstrips out the leading and the trailing underscores when matching the parameters. The underscore rule applies only if the name starts and ends with exactly one underscore, otherwise no replacing happens.
Testing Directives With External Templates:
1. Install 'karma-ng-html2js-preprocessor': https://github.com/karma-runner/karma-ng-html2js-preprocessornpm install karma-ng-html2js-preprocessor --save-dev
2. Add config to karma.config.js:
// preprocess matching files before serving them to the browser // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor preprocessors: { '*.html': ['ng-html2js'] }, ngHtml2JsPreprocessor: { // strip this from the file path stripPrefix: '/' //because currently all the html files are located in / root },
3. Add html into beforeEach:
describe('Testing directive', function() { var $scope, $compile, element; beforeEach(module('app')); // Add html file here beforeEach(module('directivetest.html')); beforeEach(inject(function(_$compile_, _$rootScope_) { $compile = _$compile_; $scope = _$rootScope_; })); it("Replaces the element with the appropriate content", function() { element = $compile('<a-great-eye></a-great-eye>')($scope); $scope.$digest(); expect(element.html()).toBe('lidless, wreathed in flame, 2 times'); }) });
.directive('aGreatEye', function () { return { restrict: 'E', replace: true, templateUrl: 'directivetest.html' }; }); /*directivetest.html*/ <h1>lidless, wreathed in flame, {{1 + 1}} times</h1>
Testing Directive Scope:
1. Check after a click event, scope value changed:
.directive('aGreatEye', function () { return { restrict: 'EA', replace: true, templateUrl: 'directivetest.html', link: function(scope, element) { scope.isClicked = false; element.bind('click', function() { scope.isClicked = true; }) } }; });
it("isClicked is true after click", function() { element = $compile('<a-great-eye></a-great-eye>')($scope); $scope.$digest(); element.triggerHandler('click'); expect($scope.isClicked).toBe(true); });
2. Isolated scope testing:
.directive('aGreatEye', function () { return { restrict: 'EA', replace: true, scope: {}, templateUrl: 'directivetest.html', link: function(scope, element) { scope.isClicked = false; element.bind('click', function() { scope.isClicked = true; }) } }; });
it("isolated scope testing", function() { element.triggerHandler('click'); expect(element.isolateScope().isClicked).toBe(true); });
You can no long use "element.scope()" or "$scope", you should use "element.isolateScope()".
[b]Testing Directive Scope Binding[/b]:
Tow ways binding:
.directive('aGreatEye', function () { return { restrict: 'EA', replace: true, scope: { flavor: "=" //Accpet an object }, templateUrl: 'directivetest.html', link: function(scope, element) { element.bind('click', function() { scope.isClicked = true; scope.flavor.message += " World!"; }) } }; });
beforeEach(inject(function(_$compile_, _$rootScope_) { $compile = _$compile_; $scope = _$rootScope_; $scope.goPro = {message: "Hello"}; element = $compile('<div a-great-eye flavor="goPro"></div>')($scope); $scope.$digest(); })); it("after click the scope.data should be Hello World!", function() { element.triggerHandler('click'); expect($scope.goPro.message).toBe('Hello World!'); expect(element.isolateScope().flavor.message).toBe("Hello World!"); });
Testing Speed:
Using ddescriber plugin to speed up unit testing.
Install the plugin "ddscriber for jasmine". Ctrl+Shift+D, to open the dailog. In the dialog you can choose which test to be included or not.
The code is modfied as:
/** * Created by Answer1215 on 1/16/2015. */ ddescribe('Testing directive', function() { var $scope, $compile, element; beforeEach(module('app')); beforeEach(module('directivetest.html')); beforeEach(inject(function(_$compile_, _$rootScope_) { $compile = _$compile_; $scope = _$rootScope_; $scope.goPro = {message: "Hello"}; element = $compile('<div a-great-eye flavor="goPro"></div>')($scope); $scope.$digest(); })); iit("Replaces the element with the appropriate content", function() { expect(element.html()).toContain("lidless, wreathed in flame, 2 times"); }); //it("isClicked is true after click", function() { // element.triggerHandler('click'); // expect($scope.isClicked).toBe(true); //}); iit("isolated scope testing", function() { element.triggerHandler('click'); //expect(element.isolateScope().isClicked).toBe(true); }); xit("after click the scope.data should be Hello World!", function() { element.triggerHandler('click'); expect($scope.goPro.message).toBe('Hello World!'); //expect(element.isolateScope().flavor.message).toBe("Hello World!"); }); }); xdescribe("error driective testing", function() { var $scope, $compile, element; beforeEach(module('app')); beforeEach(module('error.html')); beforeEach(inject(function(_$compile_, _$rootScope_) { $scope = _$rootScope_; $compile = _$compile_; element = $compile('<error></error>')($scope); $scope.$digest(); })); iit("Should contains alert-danger class", function() { expect(element.find('div').hasClass('alert-danger')).toBe(true); }); });
ddscribe / iit -- include
xdscribe / xit -- exclude
Testing Service:
Testing service, you need to inject the service into beforeEach.
ddescribe('testing service', function() { var SmithService; beforeEach(module('app')); beforeEach(inject(function(_SmithService_) { SmithService = _SmithService_; })); iit('should append Smith after each name', function() { expect(SmithService.getName("John")).toBe("John Smith"); }) });
This testing case is test whenever use a service to get a name we will append " Smith" to the end.
.service('SmithService', function() { var SmithService = {}; SmithService.getName = function(name) { return name + " Smith"; } return SmithService; });
Testing Controller:
Testing controller, you need to inject the $controller into beforeEach. And get ctrl instence by using:
appCtrl = $controller("AppCtrl")
ddescribe('Test Controller', function() { var ctrl; beforeEach(module('app')); beforeEach(inject(function(_$controller_) { ctrl = _$controller_("TestCtrl"); })); iit('Test Controller', function() { expect(ctrl.message).toBe("Hello"); }); });
.controller('TestCtrl', function() { var vm = this; vm.message = "Hello"; });
相关文章推荐
- AngularJS 入门3
- AngularJS 入门2
- angularJS 入门1
- AngularJS页面访问时出现页面闪烁问题的解决
- AngularJS页面访问时出现页面闪烁问题的解决
- angularjs前端框架
- 基于Angularjs实现分页
- 深入学习JavaScript的AngularJS框架中指令的使用方法
- 使用Jasmine和Karma对AngularJS页面程序进行测试
- 在AngularJS框架中处理数据建模的方式解析
- 简单讲解AngularJS的Routing路由的定义与使用
- 整理AngularJS框架使用过程当中的一些性能优化要点
- 详解JavaScript的AngularJS框架中的表达式与指令
- 深入解析AngularJS框架中$scope的作用与生命周期
- AngularJs一些记录
- angularjs animation
- 深入解析AngularJS框架中$scope的作用与生命周期
- 详解JavaScript的AngularJS框架中的表达式与指令
- 整理AngularJS框架使用过程当中的一些性能优化要点
- 简单讲解AngularJS的Routing路由的定义与使用