Mocha链式智能合约测试:如何跨it块持久化Hardhat合约状态
可行方案说明
Hardhat 网络默认会在每个it测试用例执行前后自动创建、回滚EVM快照,保证每个测试用例都运行在干净的初始链状态,这也是test1里的状态变更没法被test2读取的核心原因。要实现跨it块的状态持久化,有三种常用方案,按推荐优先级从高到低排列:
- 方案1:合并存在依赖关系的测试逻辑到同一个
it块
这是最符合单元测试隔离原则的方案,不会引入测试顺序依赖问题。你只需要把两个关联步骤的逻辑放到同一个测试用例内即可,示例:
注意所有合约调用必须加it('complete flow of update and use value', async () => { // 原test1逻辑 await contractA.updateValue(val); // 原test1的其他测试断言 // 原test2逻辑 await contractA.useUpdatedValue(); // 原test2的其他测试断言 });await等待交易确认上链,否则会出现时序错误。 - 方案2:通过测试钩子初始化共享状态
如果你只是需要两个测试都用到更新后的合约状态,不需要强制test1先执行完所有逻辑再跑test2,可以把状态更新的公共逻辑放到before/beforeEach钩子里执行,不需要依赖测试用例之间的执行顺序传递状态:describe('ContractA related tests', () => { // 套件内所有测试执行前先完成值更新 before(async () => { await contractA.updateValue(val); }); it('test1', () => { // 针对updateValue结果的断言逻辑 }); it('test2', () => { contractA.useUpdatedValue(); // 其他测试逻辑 }); }); - 方案3:关闭Hardhat默认的测试间状态回滚
如果你确实需要保留两个独立的it块、且严格按照执行顺序传递链状态,可以修改Hardhat配置关闭自动快照回滚。在hardhat.config.js/hardhat.config.ts中添加如下配置:module.exports = { mocha: { // 关闭测试用例执行后的自动快照回滚 snapshot: false } };注意:该配置会让整个测试流程共享同一份链状态,测试执行顺序、前面测试的异常都会直接影响后续所有测试的运行结果,很容易出现偶发的测试失败,非特殊场景不推荐使用。
额外提醒:不管用哪种方案,所有涉及合约状态修改的调用都必须加await等待交易被打包确认,否则会出现交易还没上链、后续逻辑已经执行的时序问题,导致测试结果不符合预期。
内容的提问来源于stack exchange,提问作者Tahlil
相关产品推荐
相关产品推荐

