You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

单元测试中如何使两个NaN判定为相等?

解决单元测试中NaN相等判定的问题

针对你用Map批量测试时遇到的NaN不相等问题,这里提供几种无需单独判断NaN的全局解决方案:

1. 自定义通用深度相等断言函数

写一个递归处理的比较函数,自动识别并判定两个NaN为相等,同时支持Map、对象、数组等嵌套结构的批量比较:

function deepEqualWithNaN(a, b) {
    // 优先处理NaN场景:两者均为NaN则判定相等
    if (Number.isNaN(a) && Number.isNaN(b)) {
        return true;
    }
    // 处理Map类型的键值对遍历比较
    if (a instanceof Map && b instanceof Map) {
        if (a.size !== b.size) return false;
        for (const [key, val] of a) {
            if (!b.has(key) || !deepEqualWithNaN(val, b.get(key))) {
                return false;
            }
        }
        return true;
    }
    // 处理普通对象/数组的递归比较
    if (typeof a === 'object' && a !== null && typeof b === 'object' && b !== null) {
        const keysA = Object.keys(a);
        const keysB = Object.keys(b);
        if (keysA.length !== keysB.length) return false;
        for (const key of keysA) {
            if (!keysB.includes(key) || !deepEqualWithNaN(a[key], b[key])) {
                return false;
            }
        }
        return true;
    }
    // 基本类型直接比较
    return a === b;
}

// 封装成断言函数,替换原有expect调用
function expectEqualWithNaN(result, expected) {
    const isEqual = deepEqualWithNaN(result, expected);
    if (!isEqual) {
        throw new Error(`Expected: <${expected}> Actual: <${result}>`);
    }
}

使用时直接调用expectEqualWithNaN(result, expected)即可,批量测试Map时无需单独处理NaN,函数会自动遍历所有键值对完成比较。

2. 扩展现有测试库的匹配器(以Jest为例)

如果使用Jest等支持扩展的测试框架,可以自定义全局匹配器,让现有断言语法支持NaN相等判定:

expect.extend({
    toBeEqualWithNaN(received, expected) {
        const pass = deepEqualWithNaN(received, expected);
        return {
            message: () => pass 
                ? `Expected: <${expected}> not to equal Actual: <${received}>`
                : `Expected: <${expected}> Actual: <${received}>`,
            pass
        };
    }
});

// 测试中直接使用
expect(result).toBeEqualWithNaN(expected);

这种方式可以保留原有测试库的语法风格,全局生效后所有批量测试场景都能自动处理NaN。

3. 轻量方案:利用JSON序列化处理

如果你的测试数据没有复杂嵌套类型(如Date、正则),可以通过序列化替换NaN为标记值来实现比较:

function equalWithNaN(a, b) {
    // 将NaN替换为统一标记,Map转为可序列化的数组
    const normalize = (val) => {
        if (val instanceof Map) return Array.from(val.entries()).map(([k, v]) => [k, normalize(v)]);
        if (typeof val === 'object' && val !== null) {
            const obj = {};
            for (const key in val) obj[key] = normalize(val[key]);
            return obj;
        }
        return Number.isNaN(val) ? '[NaN_MARKER]' : val;
    };
    return JSON.stringify(normalize(a)) === JSON.stringify(normalize(b));
}

该方案实现简单,但对特殊类型的兼容性较差,适合结构简单的测试数据。

内容的提问来源于stack exchange,提问作者Almis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 23:50:42