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

Jest spyOn监视返回函数:为何toBeCalled断言失败及解决方法

Jest spyOn 断言失败原因及修复方案

失败原因

问题核心是闭包内函数引用与返回对象方法的不一致:

  • newClient 内部的 getHello 直接调用的是闭包中定义的原始 getMsg 函数,而非返回对象 c 上挂载的 getMsg 方法。
  • 你通过 jest.spyOn(c, 'getMsg') 创建的 spy 绑定在返回对象的 getMsg 属性上,和闭包里的 getMsg 是两个完全独立的函数引用。因此执行 c.getHello() 时,只会触发闭包内的原始函数,不会触发你创建的 msgSpy。

修复方案

两种常见修改方式,核心都是让 getHello 调用返回对象上的 getMsg 方法:

方案一:通过 this 引用对象自身的 getMsg

修改 getHello 为普通函数,利用 this 指向返回对象,调用其 getMsg 方法:

it('spyOn test', () => {
  const newClient = () => {
    const getMsg = () => {
      return 'dear spyOn';
    };
    // 改用普通函数,通过 this 访问对象上的 getMsg
    const getHello = function() {
      return `Hello, ${this.getMsg()}`;
    };
    return {
      getMsg,
      getHello
    };
  };

  const c = newClient();
  const helloSpy = jest.spyOn(c, 'getHello');
  const msgSpy = jest.spyOn(c, 'getMsg');

  expect(c.getHello()).toEqual('Hello, dear spyOn');

  expect(helloSpy).toBeCalled(); // 断言通过
  expect(msgSpy).toBeCalled();   // 现在断言也能通过
});

方案二:先构建对象,让 getHello 直接引用对象的 getMsg

先创建返回对象,再让 getHello 调用对象自身的 getMsg:

it('spyOn test', () => {
  const newClient = () => {
    const client = {
      getMsg: () => 'dear spyOn',
      getHello: () => `Hello, ${client.getMsg()}`
    };
    return client;
  };

  const c = newClient();
  const helloSpy = jest.spyOn(c, 'getHello');
  const msgSpy = jest.spyOn(c, 'getMsg');

  expect(c.getHello()).toEqual('Hello, dear spyOn');

  expect(helloSpy).toBeCalled(); // 断言通过
  expect(msgSpy).toBeCalled();   // 现在断言也能通过
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 04:15:26