目录结构:
首先我们来看一下一个project创建好之后,整个工程的目录结构:
其中工具会自动生成test目录,其中放置对controllers的单元测试代码,main.js和about.js都是自动生成的。一般情况下,app/scripts/controllers下的每个文件都对应一个测试代码。
代码逻辑:
业务代码:
/**
* Created by jrzhaoxueyong on 2017/3/8.
*/
'use strict';
angular.module('webApp')
.controller('LoginCtrl', function ($rootScope, $location, $scope, AuthService) {
$scope.loginUser = function (credentials) {
$scope.credentials = {
username : '',
password : ''
};
console.log('login:', credentials);
AuthService.login(credentials);
$location.path('/natgw')
};
$rootScope.isUserAuthenticated = function () {
return AuthService.isAuthenticated();
}
});
测试代码:
'use strict';
describe('Controller: LoginCtrl', function () {
// load the controller's module
beforeEach(module('webApp'));
it('should have a method to check user is authenticated', function () {
// Initialize the controller and a mock scope
inject(function ($controller, $rootScope, $location) {
var scope = $rootScope.$new();
var authService = {
isAuthenticated: function () {
return true;
}
};
$controller('LoginCtrl', {
$scope: scope,
// place here mocked dependencies
AuthService: authService,
$rootScope: $rootScope,
$location: $location
});
expect($rootScope.isUserAuthenticated()).toBe(true);
});
});
});
上述是最简单的测试套,针对Controller
做相关测试其他如Directives
、Filters
、Factories
可以参考文章结尾的参考资料。代码样例是验证isUserAuthenticated
方法的。下面对这段代码做一个解剖:
-
describe属性:
describe
参数是一个全局的Jasmine方法,定义了一个测试套。其中有两个参数:一个字符串表示这个测试套的标题;一个函数是实现这个测试套的具体代码块。describe("A Test Suite", function() { })
-
beforeEach属性:
主要用来设置测试套的前置规则,相当于
setup
,与afterEach
作用相似,afterEach
作用于teardown
相似。beforeEach(module('webApp')); //module即加载了webApp模块
-
it属性:
一般一个
it
对应一个用例可以包含一个或多个expect
方法,it
有两个入参,第一个字符串表示这个用例的标题,第二个函数是这个用例的具体实现。it('should have a method to check user is authenticated', function () { });
-
inject属性:
打桩一些参数和方法,比如业务代码中需要
$scope
、$rootScope
、$location
、AuthService
四个入参,其中需要对AuthService
进行打桩,因为这是自定义Service
,此外$scope
是局部参数,这里需要从$rootScope
生成。其他两个参数都是全局参数,且不涉及自定义的属性。var scope = $rootScope.$new(); var authService = { isAuthenticated: function () { return true; } };
-
$controller属性:
这个属性很重要,它用来实例化
controller
,并把自己定义好的桩函数传递进去。这样后续expect
就能得到想要的结果了。$controller('LoginCtrl', { $scope: scope, // place here mocked dependencies AuthService: authService, $rootScope: $rootScope, $location: $location });
-
expect属性:
主要的测试函数,执行一个表达式,并对结果做验证。其中,验证的方法包括这里用到的
toBe
、toEqual
、toContain
、toMatch
、toBeDefined
等。expect($rootScope.isUserAuthenticated()).toBe(true);
执行用例:
至此,整个测试用例就写完了,下面看看运行结果:
Controller\web> grunt test