Jasmine - 文档(二)

简介: Jasmine - 文档(二)

前言

这是翻译的Jasmine文档第二篇,第一篇文章的地址为:

Jasmine - 文档(一)

Spies(间谍)

Jasmine有称为间谍(spies)的测试双重功能。一个spy可以监测任何函数的调用和参数的调用痕迹。Spy只能存在于定义它的describe()it()代码块内,而在每一个spec结束后将被移除。(这个语法在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(foo, 'setBar');//使用spyOn()来声明spy
    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();
  });
});

and.callThrough

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并且链式调用and.callThrough()
    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
  });
});

and.returnValue

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
  });
});

and.returnValues

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
  });
});

and.callFake

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);
  });
});

and.throwError

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");
  });
});

and.stub

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 - 文档(三)

目录
相关文章
|
3天前
|
数据采集 Web App开发 JavaScript
Puppeteer自动化:使用JavaScript定制PDF下载
在现代Web开发中,自动化工具如Puppeteer可显著提升效率并减少重复工作。Puppeteer是一款强大的Node.js库,能够控制无头Chrome或Chromium浏览器,适用于网页快照生成、数据抓取及自动化测试等任务。本文通过示例展示了如何使用Puppeteer自动化生成定制化的PDF文件,并介绍了如何通过配置代理IP、设置user-agent和cookie等技术增强自动化过程的灵活性与稳定性。具体步骤包括安装Puppeteer、配置代理IP、设置user-agent和cookie等,最终生成符合需求的PDF文件。此技术可应用于报表生成、发票打印等多种场景。
Puppeteer自动化:使用JavaScript定制PDF下载
|
JavaScript 测试技术 API
|
5月前
|
JavaScript 测试技术
【sgGoogleTranslate】自定义组件:基于Vue.js用谷歌Google Translate翻译插件实现网站多国语言开发
【sgGoogleTranslate】自定义组件:基于Vue.js用谷歌Google Translate翻译插件实现网站多国语言开发
|
5月前
|
JavaScript
VueCli3+TypeScript3项目显示Markdown内容
VueCli3+TypeScript3项目显示Markdown内容
98 0
|
JavaScript 前端开发 Java
JavaScript —— JSchallenger Basics 基础练习(测试一下你的 JS 基础)【专题一】
JavaScript —— JSchallenger Basics 基础练习(测试一下你的 JS 基础)【专题一】
120 0
|
存储 关系型数据库 测试技术
快速入门nest.js(10/10)--测试
初识Jest 很好的错误消息和内置Mocking实用程序 可靠的并行运行测试 优先运行以前失败的测试 根据测试文件花费的时间重新组织测试运行
312 0
|
移动开发 算法 前端开发
tink.js # pixi辅助插件 — 中文翻译教程
tink.js # pixi辅助插件 — 中文翻译教程
149 0
sound.js # pixi辅助插件 — 中文翻译教程
sound.js # pixi辅助插件 — 中文翻译教程
291 0
|
JavaScript 前端开发 程序员
Jasmine - 文档(一)(上)
Jasmine - 文档(一)(上)
182 1
Jasmine - 文档(一)(上)
|
存储 JSON 缓存
Ember.js 项目开发之 Ember Data
Ember.js 是一个基于MVVM模型的开源框架,该框架主要用于创建复杂的多页面应用程序。它最大的特点是:持续推出最新的特性,并不会丢弃任何旧功能。
148 0
Ember.js 项目开发之 Ember Data