拆分异步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'); }); });
额外注意事项
- 不要用setTimeout模拟链上确认:测试链的交易是即时完成的,
await交易后状态就已经更新了,延迟只会引入不必要的不确定性。 - 强化步骤校验:空的
then块可以补充实际状态检查,这样能更早发现前置步骤的问题(比如存款是否真的成功)。 - 确保函数读取最新状态:检查
getRethExchangeRate的实现,确保它直接调用合约的view函数,没有本地缓存逻辑。 - 确认Mocha-Cakes版本:旧版本的Mocha-Cakes可能存在步骤执行顺序问题,必要时可以升级到最新版。
备注:内容来源于stack exchange,提问作者user2007843
相关产品推荐
相关产品推荐

