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

如何Mock Web3.js中以太坊智能合约调用?遇TypeError问题求助

解决Web3.js合约调用模拟的TypeError问题

你遇到的TypeError: Cannot read properties of undefined (reading 'balanceOf'),本质是mock的层级不完整——Web3的合约调用是链式结构,从web3Client.eth.Contract到contract.methods.balanceOf再到.call(),每一层都需要正确mock,不能出现undefined的中间层。

下面是用mockDeep(结合Jest/ts-jest)的完整解决方案,精准模拟你需要的两段核心逻辑:

1. 完整Mock结构示例

import { mockDeep, mockReset } from 'jest-mock-extended';
import { Web3 } from 'web3';
import { getERC20Balance } from './your-file-path'; // 替换为你的目标函数路径

// 全局mock Web3类
jest.mock('web3', () => ({
  Web3: jest.fn().mockImplementation(() => mockDeep<Web3>({
    eth: {
      // 模拟Contract构造函数,返回带有methods的合约实例
      Contract: jest.fn().mockReturnValue(mockDeep({
        methods: {
          // 模拟balanceOf方法,返回带有call方法的对象
          balanceOf: jest.fn().mockReturnValue({
            call: jest.fn().mockResolvedValue('1000000000000000000') // 模拟1 ETH对应的wei值
          })
        }
      }))
    },
    utils: {
      fromWei: jest.fn().mockReturnValue('1') // 模拟wei转ether的结果
    }
  }))
}));

describe('getERC20Balance', () => {
  let mockWeb3: Web3;

  beforeEach(() => {
    mockWeb3 = new Web3();
    mockReset(mockWeb3); // 重置mock状态,避免用例间污染
  });

  it('should return correct token balance', async () => {
    const result = await getERC20Balance(mockWeb3, '0xTokenAddress', '0xWalletAddress');
    
    // 验证Contract构造函数被正确调用
    expect(mockWeb3.eth.Contract).toHaveBeenCalled();
    // 验证balanceOf方法被传入钱包地址调用
    expect(mockWeb3.eth.Contract().methods.balanceOf).toHaveBeenCalledWith('0xWalletAddress');
    // 验证最终结果符合预期
    expect(result).toBe('1');
  });
});

2. 关键Mock点说明

  • 不能跳过任何链式层级:必须确保web3Client.eth、web3Client.eth.Contract、contract.methods、contract.methods.balanceOf、balanceOf().call()每一层都被mock为非undefined的对象/函数,否则会触发属性读取错误。
  • 异步方法的mock:.call()是异步方法,要用mockResolvedValue模拟Promise返回结果;同步方法如fromWei用mockReturnValue即可。
  • 构造函数的mock:web3Client.eth.Contract是构造函数,需要手动指定它的返回值结构,mockDeep无法自动感知构造函数的返回类型。

3. 错误排查补充

如果仍出现类似错误,检查:

  • 是否正确mock了getERC20ABIOfInterest函数(如果它是外部依赖),确保返回合法的balanceOf ABI片段。
  • 确认测试中传入的web3Client是mock后的实例,而非真实Web3实例。
  • 打印contract、contract.methods、contract.methods.balanceOf的值,定位哪一层是undefined。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 16:37:45