核心插件概念

插件不仅仅用于编写供应商集成。作为测试人员,您可以编写插件来验证输入数据,断言对象上的模式验证,或确保DOM元素上的正确行为。API足够灵活,任何同步任务都可以轻松地封装在一个断言中,并在整个测试中重复使用。

本教程将向您展示如何访问Chai的插件API,使用标志通过语言链传递数据,并编写您的第一个断言(以及完整的错误消息)。完成此操作后,构建辅助函数将向您展示如何组合属性和方法以在Chai语言链上使用。

访问实用程序

Chai附带了许多实用程序来帮助构建断言,但它不会直接在chai导出中提供这些实用程序。可以通过使用chai导出的use方法访问这些实用程序,该方法接受一个函数作为参数。

chai.use(function (_chai, utils) {
  // ...
});

将使用的函数将其范围传递两个参数。第一个是chai导出,第二个是包含许多实用程序方法的对象(我们将在稍后介绍这些方法)。

包含chai导出是为了让您构建可以在多个测试文件中使用的辅助函数,或者将您的辅助函数打包为插件以与社区共享。创建辅助函数更合适的模式如下…

对于我们的辅助函数文件:test/helpers/model.js

module.exports = function (chai, utils) {
  var Assertion = chai.Assertion;

  // your helpers here
};

以及,对于我们的实际测试:test/person.js

var chai = require('chai')
  , chaiModel = require('./helpers/model')
  , expect = chai.expect;

chai.use(chaiModel);

在本文档的其余部分,我们将假设这种结构…

  • 外部文件中的辅助函数
  • chai.Assertion分配给Assertion变量
  • 所有辅助函数都将在导出函数内,位于指示的位置

现在,Assertion变量是断言链的构造函数;new Assertion(obj)现在等效于expect(obj)

使用标志

断言内部工作方式的最核心概念是标志的概念。每个断言都有一组与之关联的大多数情况下任意的标志 - 键:值对。Chai在内部使用少量这些标志,但该存储库也供开发人员扩展。

标志用法

标志实用程序在我们的use函数中作为utils.flag公开。它可以作为 getter 或 setter,具体取决于传递给它的参数数量。

var myAssert = new Assertion(obj);
utils.flag(myAssert, 'owner', 'me'); // sets key `owner` to `me`
var owner = utils.flag(myAssert, 'owner'); // get key `owner', returns value

对象标志

Chai 保留的标志中最重要的一个是object标志。这是断言的主题。

var myAssert = new Assertion('Arthur Dent');
var obj = flag(myAssert, 'object'); // obj === 'Arthur Dent';

此标志使用频率如此之高,以至于提供了一个快捷方式作为构造断言的_obj属性。

var obj = myAssert._obj; // obj === `Arthur Dent`

以下标志由Chai的核心断言使用。如果您干扰这些标志,可能会发生副作用。

  • object: (如上所示)
  • ssfi: 开始堆栈函数 - 用于防止回调堆栈在错误中显示。
  • message: 使用assert接口时要包含在错误中的附加信息。
  • negate: 当.not包含在链中时设置。
  • deep: 当.deep包含在链中时设置。由equalproperty使用
  • contains: 当includecontain用作属性时设置。更改keys的行为。
  • lengthOf: 当length用作属性时设置。更改abovebelowwithin的行为。

组合断言

在我们开始向语言链添加方法和属性之前,我们应该首先检查如何调用断言,以及失败时预期的行为。

为此,每个构造的Assertion都有一个名为assert的方法。它接受许多参数,其行为可能会根据断言是否被否定而改变。

基本断言

首先,我们将再次构造亚瑟,然后我们可以断言他就是他所说的那个人。

var arthur = new Assertion('Arthur Dent');

arthur.assert(
    arthur._obj === 'Arthur Dent'
  , "expected #{this} to be 'Arthur Dent'"
  , "expected #{this} to not be 'Arthur Dent'"
);

Chai 将检查第一个参数;如果它是true,那么断言通过,但如果它是false,则断言失败,第一个错误消息将作为chai.AssertionError的一部分抛出。相反,如果语言链被否定,它将认为false是通过,true是失败。第二个错误消息将包含在抛出的错误中。

总而言之,assert方法接受六个参数

  1. 一个布尔值(真值测试的结果)
  2. 如果第一个参数是false,则要使用的字符串错误消息
  3. 如果断言被否定且第一个参数是true,则要使用的字符串错误消息
  4. (可选)预期值
  5. (可选)实际值,默认为_obj
  6. (可选)一个布尔值,指示如果第一个参数是false,是否在消息之外显示差异

组合错误消息

如您从上面的示例中看到的那样,Chai 可以接受模板标签来动态组合错误消息。使用时,这些模板标签将被替换为相关对象的字符串化替换。有三个模板标签可用。

  • #{this}: 断言的_obj
  • #{exp}: 预期值(如果它在assert中提供)
  • #{act}: 实际值,默认为_obj,但可以被assert中提供的 value 覆盖