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

如何存根Lambda内部函数并统计调用次数?Sinon报错排查

问题根源

你遇到的报错Attempted to wrap undefined property anotherMethod as function,本质是function_2是handler函数的局部内部函数,外部测试代码根本访问不到这个函数,所以sinon没法对它创建spy。

解决方法

要测试内部函数的调用次数,核心是让测试代码能“碰得到”这些内部函数,下面是几种实用方案:

方案1:把内部函数挂载到handler上暴露出来

修改你的source.js,将内部函数挂载到handler自身,这样外部就能访问:

exports.handler = () =>{
  // 把内部函数挂载到handler上
  handler.function_1 = function function_1 () {
    return 'something';
  };
  handler.function_2 = function function_2 () {
    // 调用时也要用挂载后的引用
    handler.function_1();
    return 'something';
  };

  handler.function_2();
};

对应的测试代码调整为:

const handler = require('./source').handler;
const sinon = require('sinon');

describe('testing lambdas', () => {
  it('should call function_2 once', () => {
    // 给handler上的function_2创建spy
    const func2Spy = sinon.spy(handler, 'function_2');
    const func1Spy = sinon.spy(handler, 'function_1');
    
    // 执行handler
    handler();
    
    // 断言调用次数
    sinon.assert.calledOnce(func2Spy);
    sinon.assert.calledOnce(func1Spy);
    
    // 记得恢复原函数,避免影响其他测试
    func2Spy.restore();
    func1Spy.restore();
  });
});

方案2:单独导出内部函数(推荐)

如果内部函数逻辑独立,直接把它们单独导出,handler再引用,这种方式代码结构更清晰:

// source.js
// 单独导出内部函数
exports.function_1 = () => {
  return 'something';
};

exports.function_2 = () => {
  exports.function_1();
  return 'something';
};

exports.handler = () => {
  exports.function_2();
};

测试代码可以直接spy导出的函数:

const { handler, function_1, function_2 } = require('./source');
const sinon = require('sinon');

describe('testing lambdas', () => {
  it('should call function_2 and function_1 correctly', () => {
    const func1Spy = sinon.spy(function_1);
    const func2Spy = sinon.spy(function_2);
    
    handler();
    
    sinon.assert.calledOnce(func2Spy);
    sinon.assert.calledOnce(func1Spy);
    
    func1Spy.restore();
    func2Spy.restore();
  });
});

方案3:临时重写handler(不修改原结构的折中方案)

如果不想改动原handler的结构,可以临时重写handler内部的函数逻辑来统计调用次数,不过这种方式比较hack,尽量少用:

const sinon = require('sinon');
const source = require('./source');

describe('testing lambdas', () => {
  it('should track internal function calls', () => {
    let func1CallCount = 0;
    let func2CallCount = 0;
    
    // 保存原handler,测试后恢复
    const originalHandler = source.handler;
    source.handler = () => {
      function function_1() {
        func1CallCount++;
        return 'something';
      }
      function function_2() {
        func2CallCount++;
        function_1();
        return 'something';
      }
      function_2();
    };
    
    source.handler();
    
    // 验证调用次数
    expect(func2CallCount).toBe(1);
    expect(func1CallCount).toBe(1);
    
    // 恢复原handler
    source.handler = originalHandler;
  });
});
注意点
  • 所有spy/stub的函数测试后一定要用restore()恢复,不然会干扰其他测试用例
  • 优先选方案1或2,代码可读性和可维护性更高;方案3只适合临时场景

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 12:15:39