Chai 断言

三种断言风格

const chai = require('chai'); // 1. assert 风格(TDD) const { assert } = chai; assert.equal(3, 3); assert.deepEqual({ a: 1 }, { a: 1 }); assert.isNull(null); assert.include([1, 2, 3], 2); // 2. expect 风格(BDD,最流行) const { expect } = chai; expect(42).to.equal(42); expect('hello').to.be.a('string'); expect([1, 2, 3]).to.have.lengthOf(3); // 3. should 风格(BDD,扩展 Object.prototype) chai.should(); (42).should.equal(42); 'hello'.should.be.a('string');

expect — 链式调用与常用断言

const { expect } = require('chai'); expect(42).to.be.a('number'); expect([]).to.be.an('array'); expect('foo').to.equal('foo'); // 严格 === expect([1, 2]).to.deep.equal([1, 2]); // 深度相等 expect({ a: 1, b: 2 }).to.have.property('a', 1); expect(obj).to.have.all.keys('a', 'b'); expect([1, 2, 3]).to.include(2); expect([1, 2, 3]).to.have.members([3, 2, 1]); // 不计顺序 expect(7).to.be.above(5); expect(5).to.be.within(1, 10); expect('hello123').to.match(/\d+/);

深度相等与嵌套对象

expect({ a: { b: { c: 3 } } }).to.deep.equal({ a: { b: { c: 3 } } }); expect({ a: { b: 1 } }).to.have.nested.property('a.b', 1); expect({ arr: [1, 2, 3] }).to.have.nested.property('arr[1]', 2); expect({ a: 1, b: 2, c: 3 }).to.deep.include({ a: 1, b: 2 });

异常断言

expect(() => JSON.parse('invalid')).to.throw(SyntaxError); expect(() => throw new Error('Not found')).to.throw(/not found/i); // 异步断言 — chai-as-promised const chaiAsPromised = require('chai-as-promised'); chai.use(chaiAsPromised); await expect(Promise.reject(new Error('异步错误'))) .to.be.rejectedWith('异步错误'); await expect(asyncFunction()) .to.eventually.have.property('id');

插件

插件安装用途
chai-as-promisednpm i chai-as-promised异步/Promise 断言
sinon-chainpm i sinon-chaiSinon spy/stub 断言
chai-httpnpm i chai-httpHTTP 请求测试
chai-subsetnpm i chai-subset对象部分匹配

自定义消息与断言

// 自定义失败消息 expect(user.age, '用户年龄应为数字').to.be.a('number'); // 添加自定义断言方法 chai.Assertion.addMethod('validEmail', function () { const email = this._obj; this.assert( /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email), `期望 #{this} 是合法的邮箱地址`, `期望 #{this} 不是合法的邮箱地址` ); }); expect('user@example.com').to.be.a.validEmail();