Chai 中文文档 下载 App

数组断言完整参考 - include members subset ordering 深度比较

完整断言方法一览

断言语义示例
.include(el)包含某个元素expect([1,2,3]).to.include(2)
.include.members([...])包含所有给定元素(子集)expect([1,2,3]).to.include.members([1,2])
.members([...])成员完全匹配(默认无序)expect([1,2,3]).to.have.members([3,2,1])
.ordered.members([...])成员完全匹配(有序)expect([1,2,3]).to.have.ordered.members([1,2,3])
.lengthOf(n)数组长度expect([1,2,3]).to.have.lengthOf(3)
.empty空数组expect([]).to.be.empty
.deep.include(obj)深度匹配对象元素expect([{a:1}]).to.deep.include({a:1})
.deep.members([...])深度成员匹配元素为对象时必用
.any.members([...])包含任意一个给定成员expect([1,2]).to.have.any.members([1,5])
.all.members([...])包含所有给定成员默认行为
.includeMembers(needle)数组包含 needle 全部元素另一种子集写法
.includeDeepMembers(needle)深度子集匹配元素为对象时必用
.notInclude(el)不包含expect([1,2]).to.not.include(3)

.include —— 包含某个元素

expect([1, 2, 3]).to.include(2);           // ✅
expect([1, 2, 3]).to.include(4);           // ❌
expect(['a', 'b', 'c']).to.include('b');   // ✅

元素是对象时默认用严格相等,加 .deep 才能值比较:

expect([{ a: 1 }]).to.include({ a: 1 });          // ❌ 引用不同
expect([{ a: 1 }]).to.deep.include({ a: 1 });    // ✅ 值相同

.members —— 成员完全匹配

默认:无序匹配(集合相等)

expect([1, 2, 3]).to.have.members([3, 2, 1]);    // ✅ 顺序无所谓
expect([1, 2, 3]).to.have.members([1, 2]);       // ❌ 少了 3
expect([1, 2]).to.have.members([1, 2, 3]);       // ❌ 多了 3

数组长度和成员必须完全一致。多一个少一个都会失败。

.ordered —— 有序匹配

expect([1, 2, 3]).to.have.ordered.members([1, 2, 3]);   // ✅
expect([1, 2, 3]).to.have.ordered.members([3, 2, 1]);   // ❌ 顺序不对

.deep.members —— 深度成员匹配

元素是对象时,用 .deep 让成员匹配改为值比较:

expect([{ a: 1 }, { b: 2 }]).to.have.deep.members([{ b: 2 }, { a: 1 }]);  // ✅

.includeMembers —— 子集匹配

和 .members 不同,.includeMembers 只要求 needle 的成员全部在 haystack 中存在,haystack 可以有多余元素:

expect([1, 2, 3, 4]).to.includeMembers([1, 2]);     // ✅ haystack 包含 needle 所有成员
expect([1, 2]).to.includeMembers([1, 2, 3]);       // ❌ haystack 缺少 3

可以加 .deep.includeMembers 处理对象元素。

长度断言

expect([1, 2, 3]).to.have.lengthOf(3);
expect([]).to.have.lengthOf(0);

// 长度区间
expect([1, 2, 3]).to.have.length.above(2);
expect([1, 2, 3]).to.have.length.below(5);
expect([1, 2, 3]).to.have.length.within(2, 4);

.empty —— 空数组

expect([]).to.be.empty;
expect([1]).to.not.be.empty;

.any.members / .all.members —— 集合逻辑

const arr = [1, 2, 3];

// any:给定成员中至少一个存在即可
expect(arr).to.have.any.members([1, 5]);    // ✅ 1 存在
expect(arr).to.have.any.members([4, 5]);    // ❌ 都不存在

// all(默认):所有给定成员都必须存在
expect(arr).to.have.all.members([1, 2]);    // ✅ 都存在
expect(arr).to.have.all.members([1, 5]);    // ❌ 5 不存在

.deep.include —— 对象元素的部分匹配

// 数组里的对象包含某个属性
expect([
  { name: 'Alice', age: 30 },
  { name: 'Bob', age: 25 }
]).to.deep.include({ name: 'Alice' });  // ✅ 其中一个元素满足

注意 .deep.include 对数组的语义是:数组中至少一个元素深度等于给定对象。

常见陷阱

忘记 .deep 导致对象元素匹配失败

// ❌ 忘记加 .deep
expect([{ a: 1 }, { b: 2 }]).to.include({ a: 1 });  // 失败!不同引用

// ✅ 加上 .deep
expect([{ a: 1 }, { b: 2 }]).to.deep.include({ a: 1 });

.members 和 .includeMembers 混淆

.members 要求两边成员完全一致(集合相等),.includeMembers 只要求 needle 是 haystack 的子集。选错会导致断言语义不对。

.ordered 忘了加导致隐藏 bug

如果你期望有序数组(如按时间排序),一定要加 .ordered:

// ❌ 只检查成员,不检查顺序——可能通过但数据不对
expect(results).to.have.members(expected);

// ✅ 检查顺序
expect(results).to.have.ordered.members(expected);

assert 风格对应

assert.isArray(value);
assert.lengthOf(arr, n);
assert.include(arr, el);
assert.notInclude(arr, el);
assert.sameMembers(set1, set2);            // 无序完全匹配
assert.sameDeepMembers(set1, set2);         // 深度无序完全匹配
assert.includeMembers(needle, haystack);    // 子集
assert.includeDeepMembers(needle, haystack); // 深度子集

下一步