利用mocha进行以太坊智能合约编译部署测试

语言: CN / TW / HK

    使用智能合约编程语言solidity编写的智能合约,除了可以直接通过以太坊的工具链truffle,ganache-cli进行测试之外,还可以结合mocha进行单元测试。

     mocha单元测试本质上,还是需要对合约进行编译、部署,只不过可以通过代码的形式进行直观的操作,而不是通过truffle命令来进行编译、部署、测试。

    首先,构建工程,我们可以根据构建node项目的方式构建:

    添加依赖:package.json

"dependencies": {
    "ganache-cli": "^6.12.2",
    "mocha": "^8.2.1",
    "solc": "^0.4.26",
    "web3": "^1.3.3"
}

    项目结构这里简单遵循以太坊项目的结构建立一个contracts文件夹,用来保存合约。然后在contracts目录下新建HelloWorld.sol

pragma solidity ^0.4.23;

contract HelloWorld{
  string public name;
  constructor(string _name) public{
    name = _name;
  }
  function getName() public view returns(string){
    return name;
  }
  function changeName(string _name) public {
    name = _name;
  }
}

    编写compile.js用来编译合约:

const path = require('path')
const fs = require('fs')
const solc = require('solc')
const filepath = path.resolve(__dirname,'contracts','HelloWorld.sol')
const source = fs.readFileSync(filepath,'utf8')
module.exports = solc.compile(source,1).contracts[":HelloWorld"]

    建立test文件夹,用来保存测试代码,编写mocha测试代码:helloworld.test.js

const ganache = require('ganache-cli')
const Web3 = require('web3')
const assert = require('assert')
const web3 = new Web3(ganache.provider())

const {bytecode,interface} = require('../compile')

var helloworld;
var fetchAccounts;
beforeEach(async ()=>{
    /*
    web3.eth.getAccounts().then(fetchAccounts=>{
        console.log(fetchAccounts)
    })*/
    fetchAccounts = await web3.eth.getAccounts()
    helloworld = await new web3.eth.Contract(JSON.parse(interface))
    .deploy({data:bytecode,arguments:['abc']})
    .send({from:fetchAccounts[0],gas:'1000000'})
})

describe('HelloWorld',()=>{
    it('deploy contract',()=>{
        assert.ok(helloworld.options.address)
    })

    it('call static function',async ()=>{
        const message = await helloworld.methods.getName().call()
        assert.equal('abc',message)
    })

    it('call dynamic function',async ()=>{
        await helloworld.methods.changeName('xyz').send({from:fetchAccounts[0]})
        const message = await helloworld.methods.getName().call()
        assert.equal('xyz',message)
    })
})

    代码准备完毕,我们可以在package.json中配置测试scripts选项:

     

   之后,在命令行下运行单元测试:npm test

    

    单元测试全部通过,表示智能合约编译部署测试均正常,我们在进行测试的时候,传入了很多参数,合约部署之后,每一次调用,都需要进行真实的交易,所以需要账户信息,需要转账操作,这里面有进行静态方法调用,也有动态方法调用,因为智能合约编译之后,函数调用都是异步操作,所以使用了sync await来异步转同步,进而获取调用结果。

    以上代码全部参考知乎系列视频全栈react、nodejs结合区块链项目而来,有兴趣的可以从此进入:http://www.zhihu.com/people/ke-ai-de-xiao-tu-ji-71/zvideos?page=3