Home > Article > Web Front-end > Test AngularJS page program using Jasmine and Karma_node.js
AngularJS is the best thing to happen to JavaScript since jQuery. This is the way JavaScript development has always been intended. One of the main advantages of Angular is its dependency injection (Dependency Injection), which is very convenient for unit testing of code. But what's a little strange is that I can't find a tutorial on how to do unit testing.
Of course there are many good recommendations: using the Jasmine test framework and the Karma test executor (Test Runner); but there is no complete tutorial on how to test from scratch. So I wrote this article. I found a lot of resources online to figure out how to do it, and you don’t need to do any of that now (if you read this article in the first place).
Please tell me any errors you see until I can say this is the best practice for testing Angular apps based on Karma and Jasmine.
Introduction
This article will guide you to install all the tools you need to use Karma and Jasmine for automated testing. I don't care if you actually use TDD (Test Driven Development) or TAD (Test Assisted Development), for the purposes of this article I'm assuming you already have a file to test.
Install Karma
If you do not have Node.js installed, please download and install it yourself. After installation, open a terminal or command line and enter the command:
npm install -g karma
File structure
The file structure is not closely related to our topic, but in the following tests, the file structure I used is as follows:
Application | angular.js | angular-resource.js | Home | home.js | Tests | Home | home.tests.js | karma.config.js (will be created in the next step) | angular-mocks.js
*I am not advocating this document structure, I am showing it just as a testing example.
Configure Karma
Switch to the directory where you want to place the configuration file, then enter the following command in the terminal to create the configuration file:
karma init karma.config.js
You will be asked some questions, including which testing framework you want to use, whether you need automatic monitoring files, what tests and tested files are included, etc. In our tutorial, we keep ‘Jasmine’ as our default framework, enable automatic file detection, and include the following files:
../*.js ../**.*.js angular-mocks.js **/*.tests.js
These are relative paths, including 1) all .js files in the parent directory, 2) all .js files in all subdirectories under the parent directory, 3) angular-mock.js in the current directory, 4) And all .tests.js files in the current directory (including subdirectories) (I like to distinguish test files from other files in this way).
No matter what files you choose, make sure you include angular.js, angular-mock.js, and other files you need to use.
Start Karma
Now you can start Karma, still enter in the terminal:
karma start karma.config.js
This command will launch the browsers you listed in the configuration file on your computer. These browsers will connect to the Karma instance via sockets. You will see a list of active browsers and be informed whether they are running tests. I wish Karma had given you a summary of the final test results on each browser (e.g. 15 out of 16 passed, 1 failed), but unfortunately you can only see this information through the terminal window.
One of the standout features of Karma is that you can connect and test your code using any device on the network. Try pointing your mobile browser to the Karma service. You can find the test URL in any browser running on your computer. It should look like: http://localhost:9876/?id=5359192. You can point the browser of your phone, virtual machine, or any other device to [your IP address on the network]:9876/?id=5359192. Because Karma is running a Node.js instance, your test machine Just like a web server, tests will be sent to any browser pointed to it.
Basic testing
We assume you already have a file to test. The home.js file we want to use is as follows:
home.js
'use strict'; var app = angular.module('Application', ['ngResource']); app.factory('UserFactory', function($resource){ return $resource('Users/users.json') }); app.controller('MainCtrl', function($scope, UserFactory) { $scope.text = 'Hello World!'; $scope.users = UserFactory.get(); });
We can create our test cases in the home.test.js file. Let's start with the simple test: $scope.text should equal 'Hello World!'. In order to complete this test, we need to mock our Application module and the $scope variable. We will do this in Jasmine's beforeEach method so that we have a brand new (clean) controller and scope object at the beginning of each test case.
home.tests.js
'use strict'; describe('MainCtrl', function(){ var scope; //我们会在测试中使用这个scope //模拟我们的Application模块并注入我们自己的依赖 beforeEach(angular.mock.module('Application')); //模拟Controller,并且包含 $rootScope 和 $controller beforeEach(angular.mock.inject(function($rootScope, $controller){ //创建一个空的 scope scope = $rootScope.$new(); //声明 Controller并且注入已创建的空的 scope $controller('MainCtrl', {$scope: scope}); }); // 测试从这里开始 });
You can see from the code that we inject our own scope so we can validate its information outside of it. Also, don’t forget to mock the module itself (line 7)! We're now ready for testing:
home.tests.js
// 测试从这里开始 it('should have variable text = "Hello World!"', function(){ expect(scope.text).toBe('Hello World!); });
如果你运行这个测试,它可以在任何指向Karma的浏览器中执行,并且测试通过。
发送$resource请求
现在我们已经准备好测试 $resource 请求。要完成这个请求,我们需要使用到 $httpBackend, 它一个模拟版本的Angular $http。我们会创建另一个叫做 $httpBackend 的变量,在第二个 beforEach块中,注入 _$httpBackend_ 并将新创建的变量指向 _$httpBackend_。接下来我们会告诉 $httpBackend 如何对请求做出响应。
$httpBackend = _$httpBackend_; $httpBackend.when('GET', 'Users/users.json').respond([{id: 1, name: 'Bob'}, {id:2, name: 'Jane'}]);
我们的测试: home.tests.js
it('should fetch list of users', function(){ $httpBackend.flush(); expect(scope.users.length).toBe(2); expect(scope.users[0].name).toBe('Bob'); });
都放到一起
home.tests.js
'use strict'; describe('MainCtrl', function(){ var scope, $httpBackend; //we'll use these in our tests //mock Application to allow us to inject our own dependencies beforeEach(angular.mock.module('Application')); //mock the controller for the same reason and include $rootScope and $controller beforeEach(angular.mock.inject(function($rootScope, $controller, _$httpBackend_){ $httpBackend = _$httpBackend_; $httpBackend.when('GET', 'Users/users.json').respond([{id: 1, name: 'Bob'}, {id:2, name: 'Jane'}]); //create an empty scope scope = $rootScope.$new(); //declare the controller and inject our empty scope $controller('MainCtrl', {$scope: scope}); }); // tests start here it('should have variable text = "Hello World!"', function(){ expect(scope.text).toBe('Hello World!'); }); it('should fetch list of users', function(){ $httpBackend.flush(); expect(scope.users.length).toBe(2); expect(scope.users[0].name).toBe('Bob'); }); });
技巧
Karma会运行所有文件中的所有测试用例,如果你只想运行所有测试的一个子集,修改 describe 或 it 为 ddescribe 或 iit 来运行个别的一些测试。如果有些测试你不想运行他们,那么修改 describe 或 it 为 xdescribe 或 xit 来忽略这些代码。
你也可以在html文件的页面上运行你的测试。举例的代码如下:
home.runner.html
<!DOCTYPE html> <html> <head> <title>Partner Settings Test Suite</title> <!-- include your script files (notice that the jasmine source files have been added to the project) --> <script type="text/javascript" src="../jasmine/jasmine-1.3.1/jasmine.js"></script> <script type="text/javascript" src="../jasmine/jasmine-1.3.1/jasmine-html.js"></script> <script type="text/javascript" src="../angular-mocks.js"></script> <script type="text/javascript" src="home.tests.js"></script> <link rel="stylesheet" href="../jasmine/jasmine-1.3.1/jasmine.css"/> </head> <body> <!-- use Jasmine to run and display test results --> <script type="text/javascript"> var jasmineEnv = jasmine.getEnv(); jasmineEnv.addReporter(new jasmine.HtmlReporter()); jasmineEnv.execute(); </script> </body> </html>