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

如何在Hardhat单元测试中访问Solidity合约的public数组字段?

解决Solidity结构体数组在Hardhat测试中的访问问题

错误原因

Solidity中声明为public的数组,自动生成的getter函数必须传入索引参数才能获取对应位置的元素。你直接调用ballot.proposals()不传参数,自然会触发类型不匹配错误——因为函数期望接收一个索引值(BigNumberish类型),但你传了空参数。

解决方法

方法1:逐个访问数组元素(无需修改合约)

在测试中循环遍历每个索引,调用proposals(index)获取对应位置的Proposal结构体,再验证其字段是否符合预期:

describe('Deployment', function () {
  it('Should set the right proposal names', async function () {
    const { ballot, names } = await loadFixture(deployFixture);
    // 循环验证每个提案的名称和初始票数
    for (let i = 0; i < names.length; i++) {
      const proposal = await ballot.proposals(i);
      expect(proposal.name).to.equal(names[i]);
      expect(proposal.voteCount).to.equal(0);
    }
  });
});

方法2:添加自定义函数批量获取数组(需要修改合约)

如果想一次性获取整个提案数组,可以在Solidity合约中添加一个自定义view函数,直接返回整个proposals数组:

pragma solidity ^0.8.9;

contract Ballot {
  struct Proposal {
    string name;
    uint voteCount;
  }

  Proposal[] public proposals;

  constructor(string[] memory proposalNames) {
    for (uint i = 0; i < proposalNames.length; i++) {
      proposals.push(Proposal({
        name: proposalNames[i],
        voteCount: 0
      }));
    }
  }

  // 新增批量获取提案的函数
  function getAllProposals() public view returns (Proposal[] memory) {
    return proposals;
  }
}

之后在测试中直接调用这个函数,批量验证所有提案:

describe('Deployment', function () {
  it('Should set the right proposal names', async function () {
    const { ballot, names } = await loadFixture(deployFixture);
    const allProposals = await ballot.getAllProposals();
    // 遍历验证每个提案的字段
    allProposals.forEach((proposal, index) => {
      expect(proposal.name).to.equal(names[index]);
      expect(proposal.voteCount).to.equal(0);
    });
  });
});

注:如果数组元素数量极大,批量获取会消耗较多Gas,但单元测试环境下无需顾虑此问题。

内容的提问来源于stack exchange,提问作者Joey Yi Zhao

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 09:22:48