AngularJS测试二 jasmine测试路由 控制器 过滤器 事件 服务

测试应用

1.测试路由

我们需要检测路由是否在运作,是否找到了,或者是404了。我们要确认路由事件触发了,预期的模板是否真的加载了。既然路由会改变页面的地址(URL)和页面内容,我们需要检测路由是否被加载了,页面是否找到了,在这中间发生了什么。

一段简单的路由代码:

angular.module(‘myApp‘, [‘ngRoute‘])
.config(function($routeProvider) {
$routeProvider
.when(‘/‘, {
templateUrl: ‘views/main.html‘,
controller: ‘HomeController‘})
.when(‘/login‘, {
templateUrl: ‘views/login.html‘,
controller: ‘LoginController‘})
.otherwise({redirectTo ‘/‘});
})

测试路由我们需要做以下几件事:

(1)注入$route、$location和$rootScope服务。
(2)建立一个模拟的后端来处理XHR,获取模板代码。
(3)设置一个地址,运行一个$digest生命周期

Step1:在测试中引用服务,并设置一个模拟后端,从templateUrl获取模板。可以用$httpBackend来创建断言来判断指定模板被加载了.

describe(‘Routes test‘, function() {
// 在测试中模拟模块
beforeEach(module(‘myApp‘));
var location, route, rootScope;
beforeEach(inject(
function(_$location_, _$route_, _$rootScope_) {
location = _$location_;
route = _$route_;
rootScope = _$rootScope_;
}));
describe(‘index route‘, function() {
beforeEach(inject(
function($httpBackend) {
$httpBackend.expectGET(‘views/home.html‘)
.respond(200, ‘main HTML‘);
}));
// 我们的测试代码放在这里
});
});

Step2:
为了用单元测试来测试路由,我们需要模拟路由在生产中的运作。路由借助于digest生命周期来运行,当location被设置以后,它使用一个
digest循环周期来处理路由,改变页面内容,然后结束本次路由。了解了这些之后,我们就需要解释测试中路径的变更。

在测试中,我们打算在应用的index路由上测试两个状态:当用户导航到首页时,指定的控制器会给他们显示首页;当用户导航到一个未知路由时,他们会按照在otherwise函数中定义的那样被带到首页。

我们可以通过建立$location服务来传递路径的方式测试这些条件。为了触发location请求,我们要运行一个digest周期(在$rootScope上),然后检测控制器是符合预期的(在本例中,是“HomeController”)。

it(‘should load the index page on successful load of /‘,
function() {
location.path(‘/‘);
rootScope.$digest(); // 调用digest循环
expect(route.current.controller)
.toBe(‘HomeController‘)
});
it(‘should redirect to the index path on non-existent
route‘, function() {
location.path(‘/definitely/not/a/_route‘);
rootScope.$digest();
expect(route.current.controller)
.toBe(‘HomeController‘)

});

2.测试控制器

在建立单元测试的过程中,需要确保:
建立了测试来模拟模块;
用一个已知的作用域实例来存储控制器的一个实例;
基于作用域来测试我们的预期。

要初始化一个控制器实例,需要使用$new()方法从$rootScope创建某作用域的一个新实例。这个新实例会建立Angular在运行时使用的作用域继承。有了这个作用域,就可以初始化一个新的控制器,把这个作用域作为控制器的$scope传递过去。

describe(‘Unit controllers: ‘, function(){
// 模拟myApp模块
beforeEach(module(‘myApp‘));
describe(‘FrameController‘, function() {
// 局部变量
var FrameController, scope;
beforeEach(inject(
function($controller, $rootScope) {
// 创建子作用域
scope = $rootScope.$new();
// 创建FrameController的新实例
FrameController = $controller(‘FrameController‘,
{ $scope: scope });
}));
// 我们的测试代码放在这里
});

});

在FrameController里,我们有一个时钟在应用顶部显示当前时间。我们也可以访问一个用户和他的时区。具体的控制器的代码如下

angular.module(‘myApp.controllers‘, [])
.controller(‘FrameController‘,
function($scope, $timeout) {
$scope.time = {
today: new Date()
};
$scope.user = {
timezone: ‘US/Pacific‘
}
var updateClock = function() {
$scope.time.today = new Date();
};
var tick = function() {
$timeout(function() {
$scope.$apply(updateClock);
tick();
}, 1000);
}
tick();

});

我们要测试控制器的两个功能:时间已被定义;用户已被定义,并且有时区。

it(‘should have today set‘, function() {
expect(scope.time.today).toBeDefined();
});
it(‘should have a user set‘, function() {
expect(scope.user).toBeDefined();

});

再举个简单易懂的例子:

//创建一个scope对象,true表示它不会继承父级的变量,以免带来困扰

var scope=$rootScope.$new(true);

//找到SomeController,并对scope进行初始化

$controller(‘$SomeController‘,{$scope:scope});  //在这里也可以注入其他被mock的service或resolve的对象

//期待scope上应该出现一个name属性,其值为some one

$expect(scope.name).toEqual(‘some one‘);

//期待scope上应该出现一个greeting函数,调用它后的值为hello,some one

$expect(scope.greeting()).toEqual(‘hello,some one‘);

3.测试工厂和服务

Service可以是函数,可以是类,也可以是变量,所以测试起来没什么固定的形式,但是步骤和原理是相似的。

注入这个Service,把它保存为一个变量;

如果是函数,就调用它;如果是类,就new它,然后检查成员;如果是变量,就对比它的值。

var myClass;

//注入

beforeEach(inject(function(_MyClass_){

MyClass=_MyClass_;   //赋给外部变量,以便后面的测试中使用

}));

it(‘someMethod should be 2‘,function(){

var obj=new MyClass();

expect(obj.someMethod()).toEqual(2);

});

4.测试过滤器

首先,要访问过滤器,只需简单地把$filter服务注入到我们的测试中。这样我们就得到了一个在此过程中查找过滤器的途径:
describe(‘Unit: Filter tests‘, function() {
var filter;
// 在测试中模拟我们的引用
beforeEach(module(‘myApp‘));
beforeEach(inject(function($filter) {
filter = $filter;
}));
});
有了对控制器的访问,在过滤器的输出上设置预期就是很容易的事了。
it(‘should give us two decimal points‘,
function() {
expect(filter(‘number‘)(123, 2)).toEqual(‘123.00‘);
});

5.测试模板

测试模板时,我们着重于确保:特定的内容模板被加载了,模板中特定的数据也在视图中显示了。

可以建立一个断言:模板正常加载了。要做到这个,需要建立测试来期望对主页模板的一个请求,并且执行一个视图的变更来验证它是不是真的加载了。

describe(‘Unit: Templates‘, function() {
var $httpBackend,
location,
route,
rootScope;
beforeEach(module(‘myApp‘));
beforeEach(inject(
function(_$rootScope_, _$route_, _$httpBackend_, _$location_){
location = _$location_;
rootScope = _$rootScope_;
route = _$route_;
$httpBackend = _$httpBackend_;
}));
afterEach(function() {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
// 我们的测试代码放在这里
});
现在,可以建立测试来反映导航到应用不同部分时的预期。
it(‘loads the home template at /‘, function() {
$httpBackend.expectGET(‘templates/home.html‘)
.respond(200);
location.path(‘/‘);
rootScope.$digest(); // 调用digest循环
$httpBackend.flush();
});
it(‘loads the dashboard template at /dashboard‘, function() {
$httpBackend.expectGET(‘templates/dashboard.html‘)
.respond(200);
location.path(‘/dashboard‘);
rootScope.$digest(); // 调用digest循环
$httpBackend.flush();
});

注意,我们并未在测试中返回一个模板(是.respond(200),而不是.respond(200, "\<div\>\</div\>"))。鉴于我们只是在验证模板是否在请求中加载了,没有必要担心到底显示了什么。

6.测试事件

当对事件的触发进行单元测试时,我们感兴趣的是它们究竟调用了什么,还有是否真的调用了正确的事件。其次,我们主要关心处理程序有它们需要的数据。
使用Jasmine的辅助方法spnOn()可以非常容易地建立事件测试。设想我们在测试一个控制器,它触发了一个$emit函数。基于这个函数,我们可以建立一个预期:事件被触发了,并且用我们所感兴趣的任意参数调用了。

describe(‘myApp‘, function() {
var scope;
beforeEach(angular.mock.module(‘myApp‘));
beforeEach(angular.mock.inject(function($rootScope) {
scope = $rootScope.$new();
});
});
测试建好之后,就可以简单地在作用域上为$emit或者$broadcase事件设置一个spyOn()调用了。

// ...
});
it(‘should have emit called‘, function() {
spyOn(scope, "$emit");
scope.closePanel(); // 示例
// 或者任意可能导致emit被调用的事件
expect(scope.$emit)
.toHaveBeenCalledWith("panel:closed",
panel.id);
});
我们也可以测试事件:设置一个事件触发后调用的$on()监听器。要执行$broadcast方法,
可以简单地在作用域上调用$broadcast,并且对事件将会导致的作用域变化建立一个预期。
// ...
it(‘should set the panel to closed state‘,
function() {
scope.$broadcast("panel:closed", 1);
expect(scope.panel.state).toEqual("closed");
});

时间: 2024-10-12 17:11:26

AngularJS测试二 jasmine测试路由 控制器 过滤器 事件 服务的相关文章

二、测试作业 你最喜欢做什么--兴趣问题清单

二.测试作业 你最喜欢做什么--兴趣问题清单 •根据迄今为止已有的经历,你真正喜欢从事的工作是什么? 设计类方面,有自主权,无明确方向. •休暇时间你最爱从事的活动是什么? 瑜伽,旅游,与朋友见面. •什么令你精疲力尽?什么能激发你的活力? 长时间的大量工作,做成一件事后的满足感. •你是重视质量,还是重视数量? 质量. •你喜欢与人共事吗? 喜欢. •你喜欢在工作时使用计算机吗? 一般. •你喜欢写作吗? 一般. •对于创作和销售你更喜欢哪一种工作? 创作. •你愿帮运气不佳的人一臂之力吗?

Android APP压力测试(二)之Monkey信息自动收集脚本

Android APP压力测试(二) 之Monkey信息自动收集脚本 前言: 上一篇Monkey介绍基本搬抄官方介绍,主要是为了自己查阅方便.本文重点介绍我在进行Monkey时如何自动收集相关信息,主要收集Monkey测试日志.手机日志.手机屏幕截图.测试手机信息,自动按次按时间点保存信息.只需轻轻一点,腾出手腾出脑想干吗干吗,执行结束应该有信息的都有收集,一定程序提升了效率,节约了时间.可以偷空看看美图.聊天扯淡...哦不,是学习提高审美观,沟通交流增进同事情感... 转载请注明出处:Find

使用 Jasmine 测试 Node 项目

在上一篇文章(Jasmine Introdunction)中,我们已经介绍了如何在浏览器中运行 Jasmine 测试框架.对于浏览器端的 JS 代码来说,这无疑是很方便的.那么 Jasmine 能否用来对服务端的代码进行测试呢?答案当然是可以.本文中,我们就将介绍如何在基于 Node 的项目中,方便快捷地运行 Jasmine 测试. 同上篇文章一样,我们依旧新建一个待测试的 JS 文件 js/Hello.js function Hello() {}; Hello.prototype.foo =

优化后的二次测试Miller_Rabin素性测试算法

ll random(ll n) { return (ll)((double)rand()/RAND_MAX*n + 0.5); } ll pow_mod(ll a,ll p,ll n) { if(p == 0) return 1; ll ans = pow_mod(a,p/2,n); ans = ans*ans%n; if(p%2) ans = ans*a%n; return ans; } bool Witness(ll a,ll n) { ll m = n-1; int j = 0; whil

十二年测试生涯随笔

 十二年测试 毕业至今入行已经十二年,经历了多个项目的洗礼,获取了很多的开发与测试方面的经验,但越是这样越发现自己的欠缺与不足,此文愿与大家一同分享这十多年来在自动化测试工作中的经验和教训. 一.天不怕地不怕的菜鸟 什么项目都敢接,什么需求都敢答应,没有评估的经验,对项目整体没有掌控力,也把握不了项目的进展和节奏,对自动化测试没有任何概念,认为就是写程序,完成测试任务就好,在这个阶段中,每做完一件事,就有巨大的幸福感和成就感填充自己的小宇宙.并且在不断重复幸福感的过程中,不断的写程序.回头看看,

第十二周测试

第十二周测试 MySort 注意:研究sort的其他功能,要能改的动代码,需要答辩 模拟实现Linux下Sort -t : -k 2的功能. 要有伪代码,产品代码,测试代码(注意测试用例的设计) 参考 Sort的实现.提交博客链接. 1 import java.util.*; 2 3 public class MySort1 { 4 public static void main(String [] args) { 5 String [] toSort = {"aaa:10:1:1",

大数据项目测试&lt;二&gt;项目的测试工作

大数据的测试工作: 1.模块的单独测试 2.模块间的联调测试 3.系统的性能测试:内存泄露.磁盘占用.计算效率 4.数据验证(核心) 下面对各个模块的测试工作进行单独讲解. 0. 功能测试 1. 性能测试 2. 自动化测试 3. 文档评审 4. 脚本开发 一.后台数据处理端 后端的测试重点,主要集中在数据的采集处理.标签计算效率.异常数据排查(功能),测试脚本编写(HiveQL).自动化脚本编写(造数据.数据字段检查等) 1.数据的采集处理(Extract-Transform-Load) ETL

Web安全测试二步走

Web安全测试也应该遵循尽早测试的原则,在进行功能测试的时候(就应该执行下面的测试Checklist安全测试场景),然后在功能测试完成之后.性能测试之前进行扫描测试,可以用工具AppScan,Hp Webinspect,AWS等漏洞扫描工具进行扫描. 第一步:比较常用的安全测试Checklist如下: 1:不登录系统,直接输入登录后的页面URL是否可以访问. 2:不登录系统,直接输入下载文件的URL是否可以下载文件. 3:退出登录后,点击浏览器的的后退按钮能否访问之前的页面. 4:手动更改URL

Angularjs总结 二

# Angularjs总结 二 # ---------- **控制器的含义:** AngularJS中的控制器是一个函数,用来向视图的作用域中添加额外的功能.用它来给作用域对象设置初始状态,并添加自定义行为. 当在页面上创建一个新的控制器时, AngularJS会生成并传递一个新的$scope给这个控制器.可以在这个控制器里初始化$scope.由于AngularJS会负责处理控制器的实例化过程,所以只需编写控制函数即可. function myController($scope) { $scop