数组断言完整参考 - 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); // 深度子集