Chai 间谍

这是 chai 断言库的附加插件。它提供了最基本的函数间谍功能和测试。

此库主要旨在为有兴趣开发 chai 插件的任何人提供一个起点。如果您正在开发模块,欢迎您将其用作起点。我还鼓励您使用编译工具,以允许模块在 node.js 和浏览器中都能工作。

安装

Node.js

Chai 间谍在 npm 上可用。

  $ npm install chai-spies

浏览器

在包含 chai.js 后,包含 chai-spies.js

<script src="chai-spies.js"></script>

插入

如果您在浏览器中使用 chai-spies,则无需执行任何操作。它将在全局命名空间中检测到 chai 并自动使用。

如果您使用的是 node,这是一个有用的部分。

const chai = require('chai')
  , spies = require('chai-spies');

chai.use(spies);

const should = chai.should()
  , expect = chai.expect;

TypeScript 设置

如果您使用 TypeScript,您可以这样导入 chai-spies

import { expect } from 'chai';
import spies from 'chai-spies';
chai.use(spies);

构建浏览器版本

目前,此包使用 rollup 来捆绑源代码。只需使用 npm run build 构建浏览器版本。

Chai 间谍 API 参考

创建间谍

在此模块中,间谍要么是空函数,要么是包装的命名函数。一旦 chai 扩展了,您就可以通过 chai 自己的界面创建间谍。

function original () {
  // do something cool
}

const spy = chai.spy(original);

// then use in place of original
ee.on('some event', spy);

// or use without original
const spyAgain = chai.spy();
ee.on('some other event', spyAgain);

spy.on

spy.on 允许在对象的现有方法上添加间谍

const array = [1, 2, 3];

chai.spy.on(array, 'push');

// or multiple spies
chai.spy.on(array, ['push', 'pop']);

也可以提供间谍方法的自定义实现

chai.spy.on(array, 'push', function (...items) {
  // custom implementation of `push` method
});

使用箭头函数,也很容易用常量替换方法实现

chai.spy.on(array, 'push', () => 5);

// or more readable :)
chai.spy.on(array, 'push', returns => 5);

spy.interface

此方法创建一个模拟对象(或间谍对象):一个接口,每个方法都有间谍。对象的这些方法要么有假的实现,要么没有实现。

// with no implementation
const arrayLike = chai.spy.interface('arrayLike', ['push', 'pop', 'filter']);

// with fake implementation
const arrayLike = chai.spy.interface({
  push(item) {
    this.__items = this.__items || [];
    return this.__items.push(item)
  },
  // other method implementations
});

arrayLike.push(5);

spy.returns(已弃用)

chai.spy.returns 只是一个简单的辅助函数,它创建一个返回常量的函数

const returnTrue = chai.spy.returns(true);

returnTrue(); // true

最好使用箭头函数

const returnTrue = chai.spy(returns => true);

沙箱

沙箱是一组间谍。沙箱允许跟踪对象上的方法,并在 restore 调用时恢复原始方法。要创建沙箱

const sandbox = chai.spy.sandbox();

describe('Array', () => {
  let array;

  beforeEach(() => {
    array = [];
    sandbox.on(array, ['push', 'pop']);
  });

  afterEach(() => {
    sandbox.restore(); // restores original methods on `array`
  })

  it('allows to add items', () => {
    array.push(1);

    expect(array.push).to.have.been.called.with(1);
  });
});

chai.spy.onchai.spy.restore 绑定到默认沙箱。因此,要恢复所有被 chai.spy.on 间谍的方法,只需调用 chai.spy.restore()(没有参数)。

restore 方法接受 2 个可选参数:要恢复的对象和要恢复的方法或方法。因此,这些调用也有效

const array = [1, 2, 3];

chai.spy.on(array, ['push', 'pop']);

chai.spy.restore(array) // restores all methods on object
chai.spy.restore(array, 'push') // restores only `push` method

断言

.spy

断言对象是一个间谍。

expect(spy).to.be.spy;
spy.should.be.spy;

.called

断言一个间谍已经被调用。否定通过。

expect(spy).to.have.been.called();
spy.should.have.been.called();

请注意,called 可以用作链式方法。

.with

断言一个间谍至少被调用一次,即使提供了更多参数,也要使用给定的参数。

spy('foo');
expect(spy).to.have.been.called.with('foo');
spy.should.have.been.called.with('foo');

对于 spy('foo', 'bar')spy(); spy('foo') 也会通过。

如果使用多个参数,则断言间谍至少被调用一次,并且使用所有给定的参数。

spy('foo', 'bar', 1);
expect(spy).to.have.been.called.with('bar', 'foo');
spy.should.have.been.called.with('bar', 'foo');

.with.exactly

类似于 .with,但只有当参数列表与提供的参数列表完全相同才会通过。

spy();
spy('foo', 'bar');
expect(spy).to.have.been.called.with.exactly('foo', 'bar');
spy.should.have.been.called.with.exactly('foo', 'bar');

对于 spy('foo')spy('bar')spy('bar'); spy('foo')spy('foo'); spy('bar')spy('bar', 'foo')spy('foo', 'bar', 1) 不会通过。

也可以用于带有单个参数的调用。

.always.with

断言每次间谍被调用时,参数列表都包含给定的参数。

spy('foo');
spy('foo', 'bar');
spy(1, 2, 'foo');
expect(spy).to.have.been.called.always.with('foo');
spy.should.have.been.called.always.with('foo');

.always.with.exactly

断言间谍从未被调用过,调用参数列表不同于提供的参数列表。

spy('foo');
spy('foo');
expect(spy).to.have.been.called.always.with.exactly('foo');
spy.should.have.been.called.always.with.exactly('foo');

.nth(n).called.with

断言间谍的第 n 次调用已使用提供的参数列表进行。此断言还有其他三种形式

  • .first.called.with
  • .second.called.with
  • .third.called.with
spy('foo');
spy('bar');
spy('baz');
spy('foobar');
expect(spy).to.have.been.first.called.with('foo');
spy.should.have.been.first.called.with('foo');
expect(spy).on.nth(5).be.called.with('foobar');
spy.should.on.nth(5).be.called.with('foobar');

这些断言要求间谍至少被调用所需次数,例如

spy('foo');
spy('bar');
expect(spy).to.have.been.third.called.with('baz');
spy.should.have.been.third.called.with('baz');

不会通过,因为间谍没有被调用第三次。

.once

断言一个间谍只被调用了一次。

expect(spy).to.have.been.called.once;
expect(spy).to.not.have.been.called.once;
spy.should.have.been.called.once;
spy.should.not.have.been.called.once;

.twice

断言一个间谍被调用了两次。

expect(spy).to.have.been.called.twice;
expect(spy).to.not.have.been.called.twice;
spy.should.have.been.called.twice;
spy.should.not.have.been.called.twice;

.exactly(n)

断言一个间谍被精确地调用了 n 次。

expect(spy).to.have.been.called.exactly(3);
expect(spy).to.not.have.been.called.exactly(3);
spy.should.have.been.called.exactly(3);
spy.should.not.have.been.called.exactly(3);

.min(n) / .at.least(n)

断言一个间谍被调用了至少 n 次。

expect(spy).to.have.been.called.min(3);
expect(spy).to.not.have.been.called.at.least(3);
spy.should.have.been.called.at.least(3);
spy.should.not.have.been.called.min(3);

.max(n) / .at.most(n)

断言一个间谍被调用了最多 n 次。

expect(spy).to.have.been.called.max(3);
expect(spy).to.not.have.been.called.at.most(3);
spy.should.have.been.called.at.most(3);
spy.should.not.have.been.called.max(3);

.above(n) / .gt(n)

断言一个间谍被调用了超过 n 次。

expect(spy).to.have.been.called.above(3);
expect(spy).to.not.have.been.called.gt(3);
spy.should.have.been.called.gt(3);
spy.should.not.have.been.called.above(3);

.below(n) / .lt(n)

断言一个间谍被调用了少于 n 次。

expect(spy).to.have.been.called.below(3);
expect(spy).to.not.have.been.called.lt(3);
spy.should.have.been.called.lt(3);
spy.should.not.have.been.called.below(3);

测试

测试使用 mocha 以 BDD 接口编写。可以使用 npm test 执行 Node 测试。可以通过打开 test/browser/index.html 查看浏览器测试。

贡献者

项目:chai-spies
仓库年龄:3 年 2 个月
活跃度:26 天
提交次数:77 次
文件:12 个
作者
48 Jake Luer 62.3%
7 Glenn Jorde 9.1%
4 Keith Cirkel 5.2%
3 = 3.9%
3 Sergiy Stotskiy 3.9%
2 JamesMaroney 2.6%
2 PG Herveou 2.6%
2 Ryckes 2.6%
1 Veselin Todorov 1.3%
1 Steffen 1.3%
1 Daniel Walker 1.3%
1 Domenic Denicola 1.3%
1 Andre Jaenisch 1.3%
1 PG 1.3%

许可证

(MIT 许可证)

版权所有 (c) 2012 Jake Luer jake@alogicalparadox.com

特此免费授予任何获得本软件和相关文档文件(“软件”)副本的人无限制地处理软件的权利,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或出售软件副本,以及允许获得软件的人员这样做,但须符合以下条件

以上版权声明和本许可声明应包含在软件的所有副本或实质部分中。

软件按“原样”提供,不提供任何形式的明示或暗示保证,包括但不限于适销性、特定用途适用性和非侵权的保证。在任何情况下,作者或版权持有人均不对因软件或使用或以其他方式处理软件而产生的任何索赔、损害或其他责任承担责任,无论是在合同、侵权行为或其他方面产生的。