Jasmine有称为间谍(spies)的测试双重功能。一个spy可以监测任何函数的调用和参数的调用痕迹。Spy只能存在于定义它的describe()it()代码块内,而在每一个spec(即it)结束后将被移除。(这个语法在Jasmine2.0才改变的)

有几个特别的Matchers与spy相互作用: 
toHaveBeenCalled():在spy被调用是返回true; 
toHaveBeenCalledTimes():在spy调用指定次数的时候会通过测试; 
toHaveBeenCalledWith():如果匹配任一调用的参数列表,则返回true。

例子:

describe("A spy", function() {
var foo, bar = null; beforeEach(function() {
foo = {
setBar: function(value) {
bar = value;
}
};
/*使用spyOn()来声明spy*/
spyOn(foo, 'setBar'); foo.setBar(123);
foo.setBar(456, 'another param');
}); it("tracks that the spy was called", function() {
/*测试spy是否调用*/
expect(foo.setBar).toHaveBeenCalled();
}); it("tracks that the spy was called x times", function() {
/*测试spy是否调用两次*/
expect(foo.setBar).toHaveBeenCalledTimes(2);
}); it("tracks all the arguments of its calls", function() {
/*测试spy调用时的参数列表是否匹配*/
expect(foo.setBar).toHaveBeenCalledWith(123);
expect(foo.setBar).toHaveBeenCalledWith(456, 'another param');
}); it("stops all execution on a function", function() {
/*spy的调用并不会影响真实的值,所以bar仍然是null*/
expect(bar).toBeNull();
});
});

Spy通过链式调用and.callThrough,除了追踪所有的调用之外,它将委托实际的实现值。例如:

 describe("A spy, when configured to call through", function() {
var foo, bar, fetchedBar; beforeEach(function() {
foo = {
setBar: function(value) {
bar = value;
},
getBar: function() {
return bar;
}
}; spyOn(foo, 'getBar').and.callThrough(); //定义spy并且链式调用 foo.setBar(123);
fetchedBar = foo.getBar(); //调用spy
}); it("tracks that the spy was called", function() {
expect(foo.getBar).toHaveBeenCalled();
}); it("should not affect other functions", function() {
expect(bar).toEqual(123);
}); it("when called returns the requested value", function() {
expect(fetchedBar).toEqual(123); //fetchedBar为函数实际返回的值。
});
});

将上述代码与以下代码对比:

 describe("A spy, when configured to call through", function() {
var foo, bar, fetchedBar; beforeEach(function() {
foo = {
setBar: function(value) {
bar = value;
},
getBar: function() {
return bar;
}
}; spyOn(foo, 'getBar'); //不再链式调用and.callThrough() foo.setBar(123);
fetchedBar = foo.getBar();
}); it("tracks that the spy was called", function() {
expect(foo.getBar).toHaveBeenCalled();
}); it("should not affect other functions", function() {
expect(bar).toEqual(123);
}); it("when called returns the requested value", function() {
expect(fetchedBar).toBeUndefined(); //此时的fetchedBar不再是函数返回的实际值,而是undefined
});
});

Spy通过链式调用and.returnValue,所有调用spy的都将返回一个指定值。例如:

 describe("A spy, when configured to fake a return value", function() {
var foo, bar, fetchedBar; beforeEach(function() {
foo = {
setBar: function(value) {
bar = value;
},
getBar: function() {
return bar;
}
}; spyOn(foo, "getBar").and.returnValue(745); //指定返回745 foo.setBar(123);
fetchedBar = foo.getBar();
}); it("tracks that the spy was called", function() {
expect(foo.getBar).toHaveBeenCalled();
}); it("should not affect other functions", function() {
expect(bar).toEqual(123);
}); it("when called returns the requested value", function() {
expect(fetchedBar).toEqual(745); //返回特定值为745
});
});

Spy通过链式调用and.returnValues,所有调用该spy的函数都将按顺序返回一些特定的值,直到返回值队列的最后,这之后的所有调用将返回undefined。例如:

 describe("A spy, when configured to fake a series of return values", function() {
var foo, bar; beforeEach(function() {
foo = {
setBar: function(value) {
bar = value;
},
getBar: function() {
return bar;
}
}; spyOn(foo, "getBar").and.returnValues("fetched first", "fetched second"); foo.setBar(123);
}); it("tracks that the spy was called", function() {
foo.getBar(123);
expect(foo.getBar).toHaveBeenCalled();
}); it("should not affect other functions", function() {
expect(bar).toEqual(123);
}); it("when called multiple times returns the requested values in order", function() {
expect(foo.getBar()).toEqual("fetched first"); //第一次调用,返回队列的第一个值
expect(foo.getBar()).toEqual("fetched second"); //第二次调用,返回队列的第二个值
expect(foo.getBar()).toBeUndefined(); //之后的调用都将返回undefined
});
});

Spy通过调用and.callFake,所有调用该spy的都将调用其提供的函数,例如:

 describe("A spy, when configured with an alternate implementation", function() {
var foo, bar, fetchedBar; beforeEach(function() {
foo = {
setBar: function(value) {
bar = value;
},
getBar: function() {
return bar;
}
}; spyOn(foo, "getBar").and.callFake(function() {
return 1001;
}); foo.setBar(123);
fetchedBar = foo.getBar();
}); it("tracks that the spy was called", function() {
expect(foo.getBar).toHaveBeenCalled();
}); it("should not affect other functions", function() {
expect(bar).toEqual(123);
}); it("when called returns the requested value", function() {
expect(fetchedBar).toEqual(1001);
});
});

Spy链式调用and.throwError,调用该spy的将以一个错误的形式抛出特殊返回值,例如:

 describe("A spy, when configured to throw an error", function() {
var foo, bar; beforeEach(function() {
foo = {
setBar: function(value) {
bar = value;
}
}; spyOn(foo, "setBar").and.throwError("quux");
}); it("throws the value", function() {
expect(function() {
foo.setBar(123)
}).toThrowError("quux");
});
});

Spy链式调用以上某一个策略后,可以调用and.stub随时返回之前保存的原始数据,而不进行修改。例如:

 describe("A spy", function() {
var foo, bar = null; beforeEach(function() {
foo = {
setBar: function(value) {
bar = value;
}
}; spyOn(foo, 'setBar').and.callThrough();
}); it("can call through and then stub in the same spec", function() {
foo.setBar(123); //调用策略and.callThrough()所定义的spy
expect(bar).toEqual(123); //bar数值被修改为123 foo.setBar.and.stub(); //调用and.stub()
bar = null; foo.setBar(123);//调用spy
expect(bar).toBe(null); //bar不再返回and.callThrough()的实现值
});
});

其他跟踪属性

任何调用spy的都将被追踪,并且暴露在calls的属性中。

calls属性有:

1、.calls.any() : 一次都没调用时返回false,一旦调用至少一次就返回true;

2. .calls.count():返回spy调用的次数

3. .calls.argsFor(index):返回第index+1次调用时传递的参数,index从0开始;

4. .calls.allArgs():以数组的形式返回调用时传递的所有参数;

5. .calls.all():以对象形式返回上下文(this),以及所有传递的参数;

6. .calls.mostRecent():以对象形式返回最近一次调用的上下文(this),以及传递的参数;

7. .calls.first():以对象形式返回第一次调用的上下文(this),以及传递的参数;(当检查.calls.all().calls.mostRecent().calls.first()返回的对象时,.object属性指向的是调用该spy的this对象)

8. .calls.reset():清空spy的所有追踪。

上述属性值,例子如下:

 describe("A spy", function() {
var foo, bar = null; beforeEach(function() {
foo = {
setBar: function(value) {
bar = value;
}
}; spyOn(foo, 'setBar');
});
it("tracks if it was called at all", function() {
expect(foo.setBar.calls.any()).toEqual(false); foo.setBar(); expect(foo.setBar.calls.any()).toEqual(true);
});
it("tracks the number of times it was called", function() {
expect(foo.setBar.calls.count()).toEqual(0); foo.setBar();
foo.setBar(); expect(foo.setBar.calls.count()).toEqual(2);
});
it("tracks the arguments of each call", function() {
foo.setBar(123);
foo.setBar(456, "baz"); expect(foo.setBar.calls.argsFor(0)).toEqual([123]);
expect(foo.setBar.calls.argsFor(1)).toEqual([456, "baz"]);
});
it("tracks the arguments of all calls", function() {
foo.setBar(123);
foo.setBar(456, "baz"); expect(foo.setBar.calls.allArgs()).toEqual([[123],[456, "baz"]]);
});
it("can provide the context and arguments to all calls", function() {
foo.setBar(123); expect(foo.setBar.calls.all()).toEqual([{object: foo, args: [123], returnValue: undefined}]);
});
it("has a shortcut to the most recent call", function() {
foo.setBar(123);
foo.setBar(456, "baz"); expect(foo.setBar.calls.mostRecent()).toEqual({object: foo, args: [456, "baz"], returnValue: undefined});
});
it("has a shortcut to the first call", function() {
foo.setBar(123);
foo.setBar(456, "baz"); expect(foo.setBar.calls.first()).toEqual({object: foo, args: [123], returnValue: undefined});
});
it("tracks the context", function() {
var spy = jasmine.createSpy('spy');
var baz = {
fn: spy
};
var quux = {
fn: spy
};
baz.fn(123);
quux.fn(456); //当检查.calls.all(),.calls.mostRecent(),.calls.first()返回的对象时,.object属性指向的是调用该spy的this对象
expect(spy.calls.first().object).toBe(baz);
expect(spy.calls.mostRecent().object).toBe(quux);
});
it("can be reset", function() {
foo.setBar(123);
foo.setBar(456, "baz"); expect(foo.setBar.calls.any()).toBe(true); foo.setBar.calls.reset(); expect(foo.setBar.calls.any()).toBe(false);
});
});

Spies:createSpy

如果没有一个函数可以spyOn,jasmine.createSpy可以创建一个“空白”的spy。该spy会像其他间谍一样追踪调用,函数等等,但是在其之后并不会有实际实现的返回值。Spies是JavaScript对象,可以这样使用:

 describe("A spy, when created manually", function() {
var whatAmI; beforeEach(function() {
whatAmI = jasmine.createSpy('whatAmI'); whatAmI("I", "am", "a", "spy");
}); it("is named, which helps in error reporting", function() {
expect(whatAmI.and.identity()).toEqual('whatAmI');
}); it("tracks that the spy was called", function() {
expect(whatAmI).toHaveBeenCalled();
}); it("tracks its number of calls", function() {
expect(whatAmI.calls.count()).toEqual(1);
}); it("tracks all the arguments of its calls", function() {
expect(whatAmI).toHaveBeenCalledWith("I", "am", "a", "spy");
}); it("allows access to the most recent call", function() {
expect(whatAmI.calls.mostRecent().args[0]).toEqual("I");
});
});

Spies:createSpyObj

为了创建一个多重spies的模拟,使用jasmine.createSpyObj()并传递一个字符串的数组,将会返回一个对象,对象包括每个字符串绑定的spy属性。例如:

 describe("Multiple spies, when created manually", function() {
var tape; beforeEach(function() {
tape = jasmine.createSpyObj('tape', ['play', 'pause', 'stop', 'rewind']); tape.play();
tape.pause();
tape.rewind(0);
}); it("creates spies for each requested function", function() {
expect(tape.play).toBeDefined();
expect(tape.pause).toBeDefined();
expect(tape.stop).toBeDefined();
expect(tape.rewind).toBeDefined();
}); it("tracks that the spies were called", function() {
expect(tape.play).toHaveBeenCalled();
expect(tape.pause).toHaveBeenCalled();
expect(tape.rewind).toHaveBeenCalled();
expect(tape.stop).not.toHaveBeenCalled();
}); it("tracks all the arguments of its calls", function() {
expect(tape.rewind).toHaveBeenCalledWith(0);
});
});

jasmine —— Spies(转)的更多相关文章

  1. angularjs自动化测试系列之jasmine

    angularjs自动化测试系列之jasmine jasmine参考 html <!DOCTYPE html> <html lang="en"> <h ...

  2. Jasmine入门(结合示例讲解)

    参考: http://www.cnblogs.com/wushangjue/p/4541209.html http://keenwon.com/1191.html http://jasmine.git ...

  3. 使用 Jasmine 进行测试驱动的 JavaScript 开发

    Jasmine 为 JavaScript 提供了 TDD (测试驱动开发)的框架,对于前端软件开发提供了良好的质量保证,这里对 Jasmine 的配置和使用做一个说明. 目前,Jasmine 的最新版 ...

  4. 前端测试框架 jasmine 的使用

    最近的项目在使用AngulaJs,对JS代码的测试问题就摆在了面前.通过对比我们选择了 Karma  + jasmine ,使用 Jasmine做单元测试 ,Karma 自动化完成,当然了如果使用 K ...

  5. Javascript单元测试框架比较Qunit VS Jasmine

    Javascript单元测试框架比较Qunit VS Jasmine 工欲行其事必先利其器,好的单元测试框架是TDD成功的一半.Javascript优秀的测试框架很多, 包括Jasmine,Qunit ...

  6. 使用karma+jasmine做单元测试

    目的 使用karma和jasmine来配置自动化的js单元测试. Karma和Jasmine Karma是由Angular团队所开发的一种自动化测试工具.链接:http://karma-runner. ...

  7. Jasmine基础语法

    简介 Jasmine 是JavaScript的测试框架,它不依赖其他框架,也不依赖DOM,更重要的是它语法简单.以下实例都是基于Jasmine 2.5.2的,并且来自官网:https://jasmin ...

  8. Jasmine入门(下)

    上一篇 Jasmine入门(上) 介绍了Jasmine以及一些基本的用法,本篇我们继续研究Jasmine的其他一些特性及其用法(注:本篇中的例子均来自于官方文档). Spy Spy用来追踪函数的调用历 ...

  9. jasmine入门

    本文来自http://blog.fens.me/nodejs-jasmine-bdd 粉丝日志 张丹   前言TDD(Test Driven Development)测试驱动开发,是敏捷开发中提出的最 ...

随机推荐

  1. D3学习笔记一

    D3学习笔记一 什么是D3? D3(全称Data Driven Documents)是一个用来做Web数据可视化的JavaScript函数库.D3也称之为D3.js. D3是2011年由Mike Bo ...

  2. ImportError: cannot import name wordnet

    ubuntu安装好nltk,调用时,出现问题: 解决: Install Setuptools: http://pypi.python.org/pypi/setuptools Install Pip: ...

  3. 提交代码至coding.net

    1.首先在本地任意目录下创建项目 2.cmd切换至该目录下,然后依次输入: git init git add . git commit -m "version 3.9" git r ...

  4. css三栏布局方案整理

    日常开发中,经常会用到css三栏布局,现将工作中常用的css 三栏布局整理如下: 什么是三栏布局: 三栏布局,顾名思义就是两边固定,中间自适应. 一. float布局 <!DOCTYPE htm ...

  5. Sequence contains no elements : LINQ error

    1.错误意思: 出现错误的原因是:你要从一个null中取的数据. 2.错误的处理 1,使用FirstOrDefault() 来代替 First() 2.使用SingleOrDefault 来代替 Si ...

  6. 网站SEO优化

    网站的优化应该迎合搜索引擎,这样才能得到事半功倍的效果! 一.站内优化 1.做好HTML头标签 标题(title):标题是网页优化中相当有分量,一般网页title主要包含一些关键词.网站名称等.关键词 ...

  7. js中random的应用

    1.生成一个随机数 var r = Math.random(); console.info(r); 结果生成一个0-1的随机数(返回0和1之间的伪随机数,可能为0,但总是小于1,[0,1)) 2.生成 ...

  8. Python OOP面向对象

    一.什么是面向对象的程序设计 1.面向过程 程序设计:核心是过程二字,过程指的是解决问题的步骤,即先干什么再干什么......面向过程的设计就好比精心设计好一条流水线,是一种机械式的思维方式. 优点是 ...

  9. ccf-201609-3 炉石传说

    问题描述 <炉石传说:魔兽英雄传>(Hearthstone: Heroes of Warcraft,简称炉石传说)是暴雪娱乐开发的一款集换式卡牌游戏(如下图所示).游戏在一个战斗棋盘上进行 ...

  10. 1003. 猜数游戏 (Standard IO)

    题目描述 有一个“就是它”的猜数游戏,步骤如下:请你对任意输入的一个三位数x,在这三位数后重复一遍,得到一个六位数,467-->467467.把这个数连续除以7.11.13,输出最后的商. 输入 ...