Chai
describe 与 it
确实,describe 和 it 不是 Chai.js 的一部分,而是 Mocha 测试框架的组成。Chai 是一个断言库,提供了一系列的断言函数,让你可以以不同的方式声明你期望代码的行为。而 Mocha 是一个测试框架,提供了用来组织和执行测试的接口,其中 describe 用来定义测试套件(test suite),it 用来定义单个测试用例(test case)。
在编写测试代码时,通常会将 Mocha 和 Chai 结合使用。Mocha 提供了测试的结构,而 Chai 提供了断言的功能。以下是结合使用 Mocha 和 Chai 的一个基本例子:
// 引入 Chai 的 expect 断言风格
const expect = require('chai').expect;
// 使用 Mocha 的 describe 函数来组织测试套件
describe('Array and Object inclusion tests', function () {
// 使用 it 函数定义一个测试用例
it('should include keys a and b', function () {
// 使用 Chai 的 expect 断言进行测试
expect({ a: 1, b: 2, c: 3 }).to.include.all.keys('a', 'b');
});
// 更多测试用例...
});
在这个例子中,describe 和 it 提供了测试的结构,而 expect 则是来自 Chai 的断言函数。
如果你在编写测试并且想要使用 describe 和 it,你需要确保你已经安装了 Mocha,并且在你的测试文件中不需要显式地引入它们,因为当你运行 Mocha 时,它会自动地在全局范围内提供这些函数。
Chai 是什么?
Chai 是一个断言库,提供了一系列的断言函数,让你可以以不同的方式声明你期望代码的行为
Expect 常用的
const chai = require('chai');
const expect = chai.expect;
// .not 断言的示例
expect(2).to.not.equal(1); // 通过,2 不等于 1
// .deep 断言的示例
expect({ a: 1 }).to.deep.equal({ a: 1 }); // 通过,对象的内容相等
// .a 断言的示例
expect('test').to.be.a('string'); // 通过,'test' 是一个字符串
// .include 断言的示例
expect([1, 2, 3]).to.include(2); // 通过,数组包含 2
expect('foobar').to.include('foo'); // 通过,字符串包含 'foo'
// .property 断言的示例
expect({ a: 1 }).to.have.property('a'); // 通过,对象有属性 'a'
// .lengthOf 断言的示例
expect([1, 2, 3]).to.have.lengthOf(3); // 通过,数组长度为 3
// .match 断言的示例
expect('foobar').to.match(/^foo/); // 通过,字符串匹配正则表达式
// .throw 断言的示例
expect(() => {
throw new Error('error');
}).to.throw(); // 通过,函数抛出了错误
// .respondTo 断言的示例
expect({ method: function () {} }).to.respondTo('method'); // 通过,对象有名为 'method' 的方法
// .satisfy 断言的示例
expect(1).to.satisfy((num) => num > 0); // 通过,1 大于 0
// .closeTo 断言的示例
expect(1.5).to.be.closeTo(1.0, 0.5); // 通过,1.5 接近 1.0,差距在 0.5 以内
// .members 断言的示例
expect([1, 2, 3]).to.have.members([3, 2, 1]); // 通过,数组成员相同,顺序不考虑
// .oneOf 断言的示例
expect(1).to.be.oneOf([1, 2, 3]); // 通过,1 在给定的数组中
// .change 断言的示例
let obj = { val: 1 };
let changeVal = () => {
obj.val = 2;
};
expect(changeVal).to.change(() => obj.val); // 通过,函数改变了 obj.val
// .increase 断言的示例
let increaseVal = () => {
obj.val += 1;
};
expect(increaseVal).to.increase(() => obj.val); // 通过,函数增加了 obj.val
// .decrease 断言的示例
let decreaseVal = () => {
obj.val -= 1;
};
expect(decreaseVal).to.decrease(() => obj.val); // 通过,函数减少了 obj.val
Chai expect docs
import { expect } from 'chai';
describe('Equality tests', function () {
it('should assert that 2 equals 2', function () {
expect(2).to.equal(2);
});
it('should assert that 2 does not equal 1', function () {
expect(2).to.not.equal(1);
});
});
describe('Deep equality tests', function () {
it('should deeply equal {a: 1}', function () {
expect({ a: 1 }).to.deep.equal({ a: 1 });
});
it('should not strictly equal {a: 1}', function () {
expect({ a: 1 }).to.not.equal({ a: 1 });
});
it('should deeply include {a: 1} in an array', function () {
expect([{ a: 1 }]).to.deep.include({ a: 1 });
});
it('should not strictly include {a: 1} in an array', function () {
expect([{ a: 1 }]).to.not.include({ a: 1 });
});
it('should deeply include object property x: {a: 1}', function () {
expect({ x: { a: 1 } }).to.deep.include({ x: { a: 1 } });
});
it('should not strictly include object property x: {a: 1}', function () {
expect({ x: { a: 1 } }).to.not.include({ x: { a: 1 } });
});
it('should have deep members [{a: 1}] in an array', function () {
expect([{ a: 1 }]).to.have.deep.members([{ a: 1 }]);
});
it('should not strictly have members [{a: 1}] in an array', function () {
expect([{ a: 1 }]).to.not.have.members([{ a: 1 }]);
});
it('should have deep keys {a: 1} in a Set', function () {
expect(new Set([{ a: 1 }])).to.have.deep.keys([{ a: 1 }]);
});
it('should not strictly have keys {a: 1} in a Set', function () {
expect(new Set([{ a: 1 }])).to.not.have.keys([{ a: 1 }]);
});
it('should have deep property x: {a: 1}', function () {
expect({ x: { a: 1 } }).to.have.deep.property('x', { a: 1 });
});
it('should not strictly have property x: {a: 1}', function () {
expect({ x: { a: 1 } }).to.not.have.property('x', { a: 1 });
});
});
describe('Nested property tests', function () {
it('should have a nested property a.b[1]', function () {
expect({ a: { b: ['x', 'y'] } }).to.have.nested.property('a.b[1]');
});
it('should include the value "y" at the nested path a.b[1]', function () {
expect({ a: { b: ['x', 'y'] } }).to.nested.include({ 'a.b[1]': 'y' });
});
});
describe('Property tests', function () {
// @ts-nocheck
// 在所有测试运行之前,修改Object的原型,这通常是不推荐的做法,因为它可能影响全局环境
before(function () {
let Object: any = {};
Object.prototype.b = 2;
});
// 在所有测试运行之后,清理对Object原型的修改
after(function () {
delete Object.prototype.b;
});
it('应该有自己的属性a', function () {
// 测试对象是否有自己的属性a,不考虑从原型链继承的属性
expect({ a: 1 }).to.have.own.property('a');
});
it('应该有属性b', function () {
// 测试对象是否有属性b,这里属性b是从原型链继承的
expect({ a: 1 }).to.have.property('b');
});
it('不应该有自己的属性b', function () {
// 测试对象是否没有自己的属性b,即属性b是从原型链继承的
expect({ a: 1 }).to.not.have.own.property('b');
});
it('应该只包含自己的属性a且值为1', function () {
// 测试对象是否仅包含自己的属性a,且a的值为1
expect({ a: 1 }).to.own.include({ a: 1 });
});
it('应该包含属性b且值为2,但不是自己的属性', function () {
// 测试对象是否包含属性b且值为2,但b不是对象自己的属性,而是从原型继承的
expect({ a: 1 }).to.include({ b: 2 }).but.not.own.include({ b: 2 });
});
// @ts-check
});
describe('Array inclusion tests', function () {
it('should fail when checking if [1, 2, 3] includes 4', function () {
expect([1, 2, 3]).to.include(4, 'nooo why fail??');
});
it('should also fail when checking if [1, 2, 3] includes 4 with a custom message', function () {
expect([1, 2, 3], 'nooo why fail??').to.include(4);
});
});
const chai = require('chai');
const expect = chai.expect;
describe('测试对象和数组的成员包含关系', function () {
// 测试目标对象的键是否为 ['a', 'b'] 的超集但不完全相同
it('对象的键包含 a 和 b', function () {
expect({ a: 1, b: 2, c: 3 }).to.include.all.keys('a', 'b');
});
// 测试目标对象的键是否不完全等于 ['a', 'b']
it('对象的键不仅仅是 a 和 b', function () {
// 这里not have交互位置,都可
expect({ a: 1, b: 2, c: 3 }).to.have.not.all.keys('a', 'b');
expect({ a: 1, b: 2, c: 3 }).to.not.have.all.keys('a', 'b');
});
// 测试目标数组是否为 [1, 2] 的超集但不完全相同
it('数组包含成员 1 和 2', function () {
expect([1, 2, 3]).to.include.members([1, 2]);
});
// 测试目标数组是否不 完全等于 [1, 2]
it('数组的成员不仅仅是 1 和 2', function () {
expect([1, 2, 3]).to.not.have.members([1, 2]);
});
// 测试目标数组是否包含重复的子集成员时忽略重复
it('数组包含成员 1 和 2,忽略重复的 2', function () {
expect([1, 2, 3]).to.include.members([1, 2, 2, 2]);
});
});