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

如何用Jest正确Mock Ethers Provider测试合约调用函数?

正确Mock ethers.providers.Web3Provider 和 ethers.Contract 的 Jest 方案

你的测试问题核心是Mock没有完整覆盖ethers的调用逻辑,尤其是合约方法返回值未模拟成ethers认可的BigNumber类型,同时Web3Provider的初始化链路也需要完整Mock。以下是具体解决步骤:

1. 全局Mock ethers模块

在项目根目录创建__mocks__/ethers.js,全局替换ethers的实现,确保所有依赖都使用模拟逻辑:

const { BigNumber } = require('ethers');

module.exports = {
  providers: {
    Web3Provider: jest.fn(() => ({
      getSigner: jest.fn(() => ({
        getAddress: jest.fn().mockResolvedValue('0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266')
      }))
    }))
  },
  Contract: jest.fn(() => ({
    // 用真实BigNumber实例模拟合约返回值,避免类型错误
    cost: jest.fn().mockResolvedValue(BigNumber.from('1000000000000000000')),
    totalSupply: jest.fn().mockResolvedValue(BigNumber.from('1000'))
  })),
  BigNumber: BigNumber
};

2. 组件测试文件配置

在组件测试中Mockwindow.ethereum,并验证数据赋值逻辑:

import { mount } from '@vue/test-utils';
import YourComponent from '@/components/YourComponent.vue';

describe('YourComponent', () => {
  beforeEach(() => {
    jest.clearAllMocks();
    // 模拟window.ethereum基础结构
    window.ethereum = {
      request: jest.fn().mockResolvedValue({})
    };
  });

  it('正确获取合约数据并更新组件状态', async () => {
    const wrapper = mount(YourComponent);
    await wrapper.vm.getData();

    // 验证组件data是否被正确赋值
    expect(wrapper.vm.cost).toBe('1000000000000000000');
    expect(wrapper.vm.totalSupply).toBe('1000');

    // 验证ethers调用链路是否正确触发
    expect(ethers.providers.Web3Provider).toHaveBeenCalledWith(window.ethereum);
    expect(ethers.Contract).toHaveBeenCalled(); // 可传入合约地址、ABI做精准匹配
    expect(wrapper.vm.contract.cost).toHaveBeenCalled();
    expect(wrapper.vm.contract.totalSupply).toHaveBeenCalled();
  });
});

3. 组件getData函数的关键规范

确保组件内的异步逻辑正确处理Promise和类型转换:

// 组件内的getData示例
async getData() {
  try {
    const provider = new ethers.providers.Web3Provider(window.ethereum);
    const signer = provider.getSigner();
    const contract = new ethers.Contract(YOUR_CONTRACT_ADDRESS, YOUR_ABI, signer);
    
    const cost = await contract.cost();
    const totalSupply = await contract.totalSupply();
    
    this.cost = cost.toString();
    this.totalSupply = totalSupply.toString();
  } catch (err) {
    console.error(err);
  }
}

常见错误排查

  • 「无效BigNumber值」:必须用ethers.BigNumber.from()生成模拟返回值,不能直接传字符串/数字,保持和真实合约返回格式一致。
  • 组件data未更新:测试时必须用await等待getData异步执行完成,再做断言。
  • 「无法检测网络」:确保Web3Provider的Mock实现包含getSigner方法,避免ethers内部检测网络时抛出异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 16:50:23