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

Hardhat单元测试中如何断言合约返回的多个值?

Solidity多返回值合约的单元测试断言方法

当Solidity合约函数返回多个不同类型的值时,直接使用数组解构失效通常是因为以太坊库(比如ethers.js、web3.js)返回的是特殊的类数组/对象结构,而非普通JS数组。以下是几种可行的解决方式:


1. 直接通过索引访问返回值

不管用什么库,合约调用的返回结果都支持索引访问,这是最稳妥的方式:

// 调用合约函数获取结果
const result = await contractA.getAll();

// 按顺序取出对应返回值
const num = result[0];
const text = result[1];
const flag = result[2];

// 执行断言
expect(num).to.equal(ethers.BigNumber.from(100)); // 注意uint类型是BigNumber
expect(text).to.equal("test_data");
expect(flag).to.be.true;

2. 转换为普通数组后解构

如果偏好解构语法,只需把返回的类数组对象转换成普通JS数组即可:

// 用扩展运算符转成普通数组
const [num, text, flag] = [...(await contractA.getAll())];

// 或用Array.from方法
const [num, text, flag] = Array.from(await contractA.getAll());

// 断言逻辑同上
expect(num).to.equal(ethers.BigNumber.from(100));

3. 利用命名返回做对象解构

如果你的Solidity函数是带命名返回的(比如function getAll() returns (uint256 count, string memory content, bool isValid)),可以直接通过属性名解构:

// ethers.js支持直接按命名返回值解构
const { count, content, isValid } = await contractA.getAll();

// Truffle/web3.js则需要从returnValues中解构
const result = await contractA.getAll();
const { count, content, isValid } = result.returnValues;

// 断言
expect(count).to.equal(ethers.BigNumber.from(100));
expect(content).to.equal("test_data");

完整测试示例(Hardhat + ethers.js)

describe("ContractA", function () {
  let contractA;

  beforeEach(async function () {
    const ContractA = await ethers.getContractFactory("ContractA");
    contractA = await ContractA.deploy();
    await contractA.deployed();
  });

  it("should verify multiple return values correctly", async function () {
    // 方式1:索引访问
    const result = await contractA.getAll();
    expect(result[0]).to.equal(ethers.BigNumber.from(5));
    expect(result[1]).to.equal("Hello World");
    expect(result[2]).to.be.true;

    // 方式2:数组解构
    const [count, message, status] = [...result];
    expect(count).to.equal(ethers.BigNumber.from(5));
    expect(message).to.equal("Hello World");
    expect(status).to.be.true;

    // 方式3:命名属性解构
    const { count: namedCount, message: namedMsg, status: namedStatus } = result;
    expect(namedCount).to.equal(ethers.BigNumber.from(5));
    expect(namedMsg).to.equal("Hello World");
    expect(namedStatus).to.be.true;
  });
});

注意事项

  • Solidity的数值类型(如uint256)在ethers.js中会返回BigNumber类型,断言时要避免用普通数字直接对比,需用ethers.BigNumber.from()转换后再比较。
  • Truffle使用web3.js时,返回结果会包含returnValues对象,可同时通过索引和命名字段访问。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 04:20:18