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

拆分异步Mocha测试时如何保证步骤间状态传递正常?

拆分异步Mocha测试时如何保证步骤间状态传递正常?

我明白你遇到的问题了——把一个长测试拆分成多个步骤后,链上状态的更新没有在后续步骤里生效,导致断言失败。这其实是EVM测试环境里处理异步操作时很常见的坑,咱们一步步来解决:

问题根源分析

你已经把exchangeRate1放在了Scenario的顶层作用域,这个共享变量的思路是对的。导致失败的可能原因有这几个:

  • 多余的setTimeout:在Ganache/Hardhat这类测试链里,交易是即时确认的,await之后状态就已经上链生效了,加延迟反而会干扰测试上下文的状态同步。
  • submitBalances的执行是否真的触发了汇率更新?要确认这个函数的逻辑是否正确提交了余额更新,并且合约确实会根据这个更新调整rETH汇率。
  • getRethExchangeRate是否读取了最新链上状态?如果这个函数有本地缓存逻辑,可能会返回旧值,导致对比失败。

修正后的测试代码

咱们调整代码,去掉不必要的延迟,强化校验逻辑,确保每个异步操作都正确生效:

Scenario('Staker can make a deposit before and after updating the rETH exchange rate',  () => {
  let exchangeRate1;
  const [owner, node, trustedNode, staker, random] = accounts;

  // 前置初始化确保节点状态正确
  before(async () => {
    await registerNode({from: node});
    await registerNode({from: trustedNode});
    await setNodeTrusted(trustedNode, 'saas_1', 'node@home.com', owner);
  });

  when('the staker deposits 10 ETH', async () => {
    await deposit({from: staker, value: '10'.ether});
  });

  then('the staker should have successfully deposited 10 ETH', async () => {
    // 增加实际校验:确认staker获得了rETH
    const stakerRethBalance = await getRethBalance(staker);
    assertBN.gt(stakerRethBalance, 0, 'Staker should hold rETH after deposit');
  });

  when('the initial rETH exchange rate is retrieved', async () => {
    // 确保读取最新链上值,不要依赖缓存
    exchangeRate1 = await getRethExchangeRate();
  });

  then('the initial exchange rate should be valid', () => {
    assertBN.gt(exchangeRate1, 0, 'Initial rETH exchange rate must be positive');
  });

  when('the network ETH total is updated to 130%', async () => {
    const totalBalance = '13'.ether;
    const rethSupply = await getRethTotalSupply();
    // 确保交易被正确执行并上链
    await submitBalances(1, totalBalance, 0, rethSupply, { from: trustedNode });
  });

  then('the rETH exchange rate should change', async () => {
    // 重新读取最新汇率,避免缓存干扰
    const exchangeRate2 = await getRethExchangeRate();
    assertBN.notEqual(exchangeRate1, exchangeRate2, 'rETH exchange rate should update after network balance change');
  });

  when('the staker deposits 10 ETH again', async () => {
    await deposit({from: staker, value: '10'.ether});
  });

  then('the staker should have successfully made a second deposit', async () => {
    const stakerRethBalance = await getRethBalance(staker);
    // 校验第二次存款后余额增加
    assertBN.gt(stakerRethBalance, (await getRethExchangeRate()).mul('10'.ether), 'Staker should have more rETH after second deposit');
  });
});

额外注意事项

  1. 不要用setTimeout模拟链上确认:测试链的交易是即时完成的,await交易后状态就已经更新了,延迟只会引入不必要的不确定性。
  2. 强化步骤校验:空的then块可以补充实际状态检查,这样能更早发现前置步骤的问题(比如存款是否真的成功)。
  3. 确保函数读取最新状态:检查getRethExchangeRate的实现,确保它直接调用合约的view函数,没有本地缓存逻辑。
  4. 确认Mocha-Cakes版本:旧版本的Mocha-Cakes可能存在步骤执行顺序问题,必要时可以升级到最新版。

备注:内容来源于stack exchange,提问作者user2007843

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 08:08:14