单元测试javascript数组去重函数需断言三要素:元素唯一性、原始顺序保留、原数组不被修改;须手写预期值避免循环论证,并覆盖nan、0/-0、对象等特殊类型。

在单元测试中验证 JavaScript 数组去重函数是否正确,关键不是只检查“结果数组长度变短了”,而是要同时断言:去重后元素唯一、原始顺序保留、所有原元素都未丢失(仅重复项被剔除)。下面以常见场景为例,给出可直接落地的断言写法和注意事项。
断言去重结果的元素值与唯一性
用 expect(result).toEqual([...]) 直接比对预期数组是最清晰的方式。注意:必须手写**符合去重逻辑的期望值**,不能用 new Set() 生成后反推——那等于用实现逻辑测实现逻辑,失去测试意义。
- ✅ 正确示例(Jest):
expect(uniq([1, 2, 2, 3, 1])).toEqual([1, 2, 3]); - ❌ 避免这样写:
const expected = [...new Set([1, 2, 2, 3, 1])];
expect(uniq([1, 2, 2, 3, 1])).toEqual(expected);(循环论证)
断言顺序未被破坏
去重算法(如 filter + indexOf 或 Map 记录首次出现索引)必须保持第一次出现的顺序。仅检查 toEqual 已隐含顺序校验,但可额外加一层防御性断言:
- 验证原数组中某重复元素的首次位置,是否等于结果数组中该元素的位置:
const original = ['a', 'b', 'a', 'c'];
const result = uniq(original);
expect(result.indexOf('a')).toBe(original.indexOf('a')); - 对多个重复项分别验证,避免只测一个漏掉边界情况
断言不修改原数组(纯函数性)
多数去重函数应是纯函数——不改变输入。这是易被忽略但关键的测试点:
- ✅ 在调用前后对比原数组引用和内容:
const input = [1, 2, 2, 3];
const originalCopy = [...input]; // 浅拷贝
uniq(input);
expect(input).toEqual(originalCopy); // 内容未变
expect(input).toBe(originalCopy); // 引用也未变(若函数没重赋值 input 变量) - 尤其注意测试空数组、单元素、全重复等边界输入下的行为一致性
覆盖特殊值和类型组合
JavaScript 中 NaN !== NaN、0 === -0、对象引用比较等会让去重出错。测试需显式覆盖:
- expect(uniq([NaN, NaN, 1])).toEqual([NaN, 1]);(正确实现应把 NaN 当作相同值处理)
- expect(uniq([0, -0, 1])).toEqual([0, 1]);(主流去重通常合并 0 和 -0)
- expect(uniq([{a:1}, {a:1}, {b:2}])).toHaveLength(3);(对象默认按引用去重,结果应为 3;若需求是深比较去重,需另写逻辑并单独测试)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











