Solidity合约测试中beforeEach钩子执行失败求助
问题排查与解决方案
错误原因分析
从报错信息SyntaxError: Unexpected token 'o', "[object Obj"... is not valid JSON可以定位到核心问题:
- ABI重复解析:编译脚本
compile.js导出的abi已经是经过JSON.parse处理后的JavaScript对象,测试文件中再次调用JSON.parse(abi)会把对象转为字符串"[object Object]",进而触发JSON解析错误。 - 编译结果访问路径错误:
compile.js中output.contracts[[inboxPath]]使用了双重数组包裹路径,属于写法错误,虽当前未直接导致ABI/bytecode获取失败,但存在潜在风险。
修复步骤
1. 修正编译脚本(compile.js)
将访问编译结果的路径从双重数组改为单数组:
const path = require('path'); const fs = require('fs'); const solc = require('solc'); const inboxPath = path.resolve(__dirname, 'contracts', 'inbox.sol'); const source = fs.readFileSync(inboxPath, 'UTF-8'); var input = { language: 'Solidity', sources: { [inboxPath]: { content: source, }, }, settings: { outputSelection: { '*': { '*': ['*'], }, }, }, }; var output = JSON.parse(solc.compile(JSON.stringify(input))); // 修复:将[[inboxPath]]改为[inboxPath] module.exports = { abi: output.contracts[inboxPath]['Inbox'].abi, bytecode: output.contracts[inboxPath]['Inbox'].evm.bytecode.object, };
2. 修正测试文件(inbox.test.js)
移除对ABI的JSON.parse调用,直接使用导出的ABI对象,同时补全变量声明避免全局污染:
const assert = require('assert'); const ganache = require('ganache'); const { Web3 } = require('web3'); const web3 = new Web3(ganache.provider()); const { abi, bytecode } = require('../compile'); const { it } = require('mocha'); let accounts; let inbox; // 显式声明变量,避免隐式全局变量 beforeEach(async () => { // 获取所有账户列表 accounts = await web3.eth.getAccounts(); // 使用其中一个账户部署合约 // 修复:去掉JSON.parse(abi),直接传入abi对象 inbox = await new web3.eth.Contract(abi) .deploy({ data: bytecode, arguments: ['Hi there!'] }) .send({ from: accounts[0], gas: '1000000' }); }); describe('Inbox', () => { it('deploys a contract', () => { assert.ok(inbox.options.address); // 用断言验证合约地址存在,替代console.log }); });
验证修复
执行测试命令:
npm test
测试应正常运行并通过,验证合约部署成功。
注:bigint: Failed to load bindings属于非阻塞警告,若要消除可执行npm rebuild重新编译依赖。
内容的提问来源于stack exchange,提问作者Rishabh
相关产品推荐
相关产品推荐

