如何在Jasmine中测试柯里化函数的返回结果?
解决柯里化/绑定函数的断言问题
这个问题我之前也碰到过——bind返回的是全新的函数实例,所以用toBe做严格相等断言肯定会失败,毕竟两个函数的引用完全不一样。下面给你几个可行的解决思路:
1. 优先测试函数的行为(最推荐)
单元测试的核心是验证功能是否符合预期,而不是纠结函数的引用。与其断言“这个函数就是b”,不如断言“这个函数的行为和b绑定参数后的行为一致”。
修改你的代码示例来实现这个思路:
// 先给b加一个可验证的行为 const b = (arg) => `processed: ${arg}`; const c = (arg) => b.bind(null, arg); describe("curried function test", function() { // 测试绑定后的函数行为是否正确 it('should return a function that behaves like b with the bound argument', () => { const boundFunc = c('foo'); // 调用绑定后的函数,验证输出和直接调用b传参的结果一致 expect(boundFunc()).toBe(b('foo')); }); });
这种方法不依赖任何实现细节,不管你用bind还是自定义柯里化函数,只要功能正确,测试就能通过。
2. 验证绑定函数关联到原函数b
如果你确实需要确认生成的函数是基于b绑定而来的,可以通过以下两种方式实现:
方式A:给原函数加自定义标记
给原函数添加一个唯一的自定义属性,然后断言绑定后的函数的目标函数拥有这个标记:
const b = () => {}; // 给原函数加一个自定义标记 b.__isOriginalB = true; const c = (arg) => b.bind(null, arg); // 辅助函数:检查一个绑定函数是否关联到目标函数 function isBoundTo(boundFunc, targetFunc) { // 绑定函数的name属性会是"bound 原函数名" if (!boundFunc.name.startsWith('bound ')) return false; // 利用toString输出判断(不同JS引擎输出可能略有差异,但测试环境中稳定) return boundFunc.toString().includes(targetFunc.toString()); } describe("curried function test", function() { it('should return a function bound to b', () => { expect(isBoundTo(c('foo'), b)).toBe(true); }); });
方式B:使用自定义柯里化函数(而非原生bind)
如果是你自己实现柯里化逻辑,可以在柯里化函数中保留对原函数的引用:
// 自定义柯里化工具函数,保留原函数引用 const curry = (fn, ...initialArgs) => { const curriedFunc = (...moreArgs) => fn(...initialArgs, ...moreArgs); // 挂载原函数引用 curriedFunc.__originalFunction = fn; return curriedFunc; }; const b = () => {}; const c = (arg) => curry(b, arg); describe("curried function test", function() { it('should return a curried function referencing b', () => { expect(c('foo').__originalFunction).toBe(b); }); });
这种方式完全可控,适合你自己维护柯里化逻辑的场景。
3. 不推荐:依赖函数源码断言
你之前用JSON.stringify断言源码的方式虽然能临时解决问题,但非常脆弱——一旦原函数的源码有细微改动(比如加个空格),测试就会失败,而且不同JS引擎对函数toString的输出可能不一致,所以不推荐长期使用。
内容的提问来源于stack exchange,提问作者Pete
相关产品推荐
相关产品推荐

