用于 Chai 的 Sinon.JS 断言

用 Sinon.JS mocking 框架的断言扩展 Chai。「Extends Chai with assertions for the Sinon.JS mocking framework.」

Github星跟踪图

用于 Chai 的 Sinon.JS 断言

Sinon-Chai 为使用 Sinon.JS 的 spy、stub 和 mock 框架提供了一套自定义的断言,其中包含了 Chai 断言库。你可以通过 Sinon.JS 的所有强大的工具获得 Chai 的所有好处。

代替使用 Sinon.JS 的断言。

sinon.assert.calledWith(mySpy, "foo");

或者笨拙地试图在 spy 属性上使用 Chai 的 should 或 expect 接口。

mySpy.calledWith("foo").should.be.ok;
expect(mySpy.calledWith("foo")).to.be.ok;

你可以这样

mySpy.should.have.been.calledWith("foo");
expect(mySpy).to.have.been.calledWith("foo");

断言

所有你喜欢的 Sinon.JS 断言都进入了 Sinon-Chai。我们在这里展示了 should 语法,同时也提供了 expect equivalent。

Sinon.JS property/method Sinon–Chai 断言
called spy.should.have.been.called
callCount spy.should.have.callCount(n)
calledOnce spy.should.have.been.calledOnce
calledTwice spy.should.have.been.calledTwice
calledThrice spy.should.have.been.calledThrice
calledBefore spy1.should.have.been.calledBefore(spy2)
calledAfter spy1.should.have.been.calledAfter(spy2)
calledImmediatelyBefore spy.should.have.been.calledImmediatelyBefore(spy2)
calledImmediatelyAfter spy.should.have.been.calledImmediatelyAfter(spy2)
calledWithNew spy.should.have.been.calledWithNew
alwaysCalledWithNew spy.should.always.have.been.calledWithNew
calledOn spy.should.have.been.calledOn(context)
alwaysCalledOn spy.should.always.have.been.calledOn(context)
calledWith spy.should.have.been.calledWith(...args)
alwaysCalledWith spy.should.always.have.been.calledWith(...args)
calledOnceWith spy.should.always.have.been.calledOnceWith(...args)
calledWithExactly spy.should.have.been.calledWithExactly(...args)
alwaysCalledWithExactly spy.should.always.have.been.calledWithExactly(...args)
calledOnceWithExactly spy.should.always.have.been.calledOnceWithExactly(...args)
calledWithMatch spy.should.have.been.calledWithMatch(...args)
alwaysCalledWithMatch spy.should.always.have.been.calledWithMatch(...args)
returned spy.should.have.returned(returnVal)
alwaysReturned spy.should.have.always.returned(returnVal)
threw spy.should.have.thrown(errorObjOrErrorTypeStringOrNothing)
alwaysThrew spy.should.have.always.thrown(errorObjOrErrorTypeStringOrNothing)

关于每个断言行为的更多信息,请参见相应的 spy 方法的文档。当然,这些方法不仅适用于间谍,还适用于单个侦探、打桩和 mock 调用。

注意,你可以用 Chai 的 .not 来否定任何断言。如:对于 notCalled 使用 spy.should.have.not.been.called。

对于断言接口,没有必要使用这个库。你可以通过 expose 将 Sinon.JS 断言 直接安装到 Chai 的断言对象中。

var chai = require("chai");
var sinon = require("sinon");
sinon.assert.expose(chai.assert, { prefix: "" });

示例

使用 Chai should:

"use strict";
var chai = require("chai");
var sinon = require("sinon");
var sinonChai = require("sinon-chai");
chai.should();
chai.use(sinonChai);
function hello(name, cb) {
    cb("hello " + name);
}
describe("hello", function () {
    it("should call callback with correct greeting", function () {
        var cb = sinon.spy();
        hello("foo", cb);
        cb.should.have.been.calledWith("hello foo");
    });
});

使用 Chai expect:

"use strict";
var chai = require("chai");
var sinon = require("sinon");
var sinonChai = require("sinon-chai");
var expect = chai.expect;
chai.use(sinonChai);
function hello(name, cb) {
    cb("hello " + name);
}
describe("hello", function () {
    it("should call callback with correct greeting", function () {
        var cb = sinon.spy();
        hello("foo", cb);
        expect(cb).to.have.been.calledWith("hello foo");
    });
});

安装和使用

Node

执行 npm --save-dev sinon-chai 来启动和运行。然后:

var chai = require("chai");
var sinonChai = require("sinon-chai");
chai.use(sinonChai);

当然,你也可以把这些代码放在一个普通的测试夹具文件中;关于使用 Mocha 的例子,请看 the Sinon–Chai 测试本身

define(function (require, exports, module) {
    var chai = require("chai");
    var sinonChai = require("sinon-chai");

    chai.use(sinonChai);
});

AMD

Sinon-Chai 支持作为 AMD 模块使用,匿名注册自己(就像 Chai 一样)。所以,假设你已经配置了你的加载器,将 Chai 和 Sinon-Chai 文件映射到各自的模块 ID "chai" 和 "sinon-chai" 上,你可以按照以下方式使用它们。

define(function (require, exports, module) {
    var chai = require("chai");
    var sinonChai = require("sinon-chai");
    chai.use(sinonChai);
});

<script>标签

如果你直接用 <script> 标签将 Sinon-Chai 包含在 Chai 本身的标签之后,那么它就会自动插入到 Chai 中,并且可以使用。请注意,你也需要获得最新的 Sinon.JS 浏览器版本。

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

Ruby on Rails

感谢 Cymen Vig,现在有了 Sinon-Chai 的 Ruby gem,可以将其与 Rails asset pipeline 集成在一起。


(The first version translated by vz on 2020.08.30)

主要指标

概览
名称与所有者chaijs/sinon-chai
主编程语言JavaScript
编程语言JavaScript (语言数: 1)
平台Linux, Mac, Web browsers, Windows
许可证Other
所有者活动
创建于2012-02-13 20:35:11
推送于2024-07-25 20:00:57
最后一次提交2024-07-25 21:00:55
发布数35
最新版本名称4.0.0 (发布于 )
第一版名称1.0.0 (发布于 )
用户参与
星数1.1k
关注者数21
派生数105
提交数155
已启用问题?
问题数108
打开的问题数16
拉请求数32
打开的拉请求数4
关闭的拉请求数24
项目设置
已启用Wiki?
已存档?
是复刻?
已锁定?
是镜像?
是私有?

Sinon.JS Assertions for Chai

Sinon–Chai provides a set of custom assertions for using the Sinon.JS spy, stub, and mocking framework with the
Chai assertion library. You get all the benefits of Chai with all the powerful tools of Sinon.JS.

Instead of using Sinon.JS's assertions:

sinon.assert.calledWith(mySpy, "foo");

or awkwardly trying to use Chai's should or expect interfaces on spy properties:

mySpy.calledWith("foo").should.be.ok;
expect(mySpy.calledWith("foo")).to.be.ok;

you can say

mySpy.should.have.been.calledWith("foo");
expect(mySpy).to.have.been.calledWith("foo");

Assertions

All of your favorite Sinon.JS assertions made their way into Sinon–Chai. We show the should syntax here; the expect
equivalent is also available.

Sinon.JS property/method Sinon–Chai assertion
called spy.should.have.been.called
callCount spy.should.have.callCount(n)
calledOnce spy.should.have.been.calledOnce
calledTwice spy.should.have.been.calledTwice
calledThrice spy.should.have.been.calledThrice
calledBefore spy1.should.have.been.calledBefore(spy2)
calledAfter spy1.should.have.been.calledAfter(spy2)
calledImmediatelyBefore spy.should.have.been.calledImmediatelyBefore(spy2)
calledImmediatelyAfter spy.should.have.been.calledImmediatelyAfter(spy2)
calledWithNew spy.should.have.been.calledWithNew
alwaysCalledWithNew spy.should.always.have.been.calledWithNew
calledOn spy.should.have.been.calledOn(context)
alwaysCalledOn spy.should.always.have.been.calledOn(context)
calledWith spy.should.have.been.calledWith(...args)
alwaysCalledWith spy.should.always.have.been.calledWith(...args)
calledOnceWith spy.should.always.have.been.calledOnceWith(...args)
calledWithExactly spy.should.have.been.calledWithExactly(...args)
alwaysCalledWithExactly spy.should.always.have.been.calledWithExactly(...args)
calledOnceWithExactly spy.should.always.have.been.calledOnceWithExactly(...args)
calledWithMatch spy.should.have.been.calledWithMatch(...args)
alwaysCalledWithMatch spy.should.always.have.been.calledWithMatch(...args)
returned spy.should.have.returned(returnVal)
alwaysReturned spy.should.have.always.returned(returnVal)
threw spy.should.have.thrown(errorObjOrErrorTypeStringOrNothing)
alwaysThrew spy.should.have.always.thrown(errorObjOrErrorTypeStringOrNothing)

For more information on the behavior of each assertion, see
the documentation for the corresponding spy methods. These of course work on not only spies, but
individual spy calls, stubs, and mocks as well.

Note that you can negate any assertion with Chai's .not. E. g. for notCalled use spy.should.have.not.been.called. Similarly, note that the always methods are accessed with Chai's .always prefix; should.have.been.alwaysCalledWith will not work - instead, use should.always.have.been.calledWith.

For simplicity, this library intentionally only implements Sinon's spy methods, and does not add an interface for Sinon.assert.match. Sinon's matchers are implemented by the samsam library, so if you want a should/expect interface to assert.match you may be interested in chai-samsam, which adds a .deep.match verb that will work with Sinon matchers.

For assert interface there is no need for sinon-chai or chai-samsam. You can install Sinon.JS assertions right into Chai's assert object with expose:

var chai = require("chai");
var sinon = require("sinon");

sinon.assert.expose(chai.assert, { prefix: "" });

Examples

Using Chai's should:

"use strict";
var chai = require("chai");
var sinon = require("sinon");
var sinonChai = require("sinon-chai");
chai.should();
chai.use(sinonChai);

function hello(name, cb) {
    cb("hello " + name);
}

describe("hello", function () {
    it("should call callback with correct greeting", function () {
        var cb = sinon.spy();

        hello("foo", cb);

        cb.should.have.been.calledWith("hello foo");
    });
});

Using Chai's expect:

"use strict";
var chai = require("chai");
var sinon = require("sinon");
var sinonChai = require("sinon-chai");
var expect = chai.expect;
chai.use(sinonChai);

function hello(name, cb) {
    cb("hello " + name);
}

describe("hello", function () {
    it("should call callback with correct greeting", function () {
        var cb = sinon.spy();

        hello("foo", cb);

        expect(cb).to.have.been.calledWith("hello foo");
    });
});

Installation and Usage

Node

Do an npm install --save-dev sinon-chai to get up and running. Then:

var chai = require("chai");
var sinonChai = require("sinon-chai");

chai.use(sinonChai);

You can of course put this code in a common test fixture file; for an example using Mocha, see
the Sinon–Chai tests themselves.

AMD

Sinon–Chai supports being used as an AMD module, registering itself anonymously (just like Chai). So, assuming you
have configured your loader to map the Chai and Sinon–Chai files to the respective module IDs "chai" and
"sinon-chai", you can use them as follows:

define(function (require, exports, module) {
    var chai = require("chai");
    var sinonChai = require("sinon-chai");

    chai.use(sinonChai);
});

<script> tag

If you include Sinon–Chai directly with a <script> tag, after the one for Chai itself, then it will automatically plug
in to Chai and be ready for use. Note that you'll want to get the latest browser build of Sinon.JS as well:

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

Ruby on Rails

Thanks to Cymen Vig, there's now a Ruby gem of Sinon–Chai that integrates it with the Rails asset pipeline!