Intro to Web3.go Part 4: Testing

Marius Van Der Wijden
3 min readJul 9, 2020

--

How to use go-ethereum as a library

Many developers have asked me how they can use their favorite programming language, Go, to access the Ethereum network(s). This article is part of a series that should explain the little known ability to use go-ethereum as a library to access Ethereum. You can find part 1 of this series here, part 2 here, and part 3 here.

In the last parts, we’ve learned how to interact with a live node. Setting up a live node within your CI-Pipeline however is laborious and very error-prone. Fortunately go-ethereum provides an easy way to create a simulated blockchain in your unit tests. A bit hidden in accounts/abi/bind/backends , we provide backends.SimulatedBackend which acts almost as a drop-in replacement for ethclient.Client , which we got to know in the first part of this tutorial.

Mocking a blockchain: the SimulatedBackend

If we want to create a simulated backend, we need to pass a valid allocation and the GasLimit for the genesis block. For most use cases it makes sense to create a faucet/account that owns a lot of ether when starting the test. All precompiles need to own some ether, otherwise there are some differences between the nodes (regarding purging of empty accounts).

Two ways to create a simulated backend

Now that we created a SimulatedBackend we can use it similar to a ethclient.Client which means we can call basic functions (BalanceAt, BlockByNumber, …), deploy smart contracts and interact with them. Unfortunately we have to call backend.Commit() after every transaction, which tells the SimulatedBackend to create a new block. An easy way to circumvent this is by doing something like I did here. Basically we create a new type that embeds a SimulatedBackend and overwrites the SendTransaction function to commit after every send. The resulting type can now be used as a perfect drop-in for ethclient .

Overwrite SendTransaction to behave like ethclient.SendTransaction

Having a simulated blockchain allows us to create interesting scenarios that might not be possible to recreate with a normal node. If we don’t call Commit() after every transaction, we can influence how many transactions are mined into a block. With Rollback() , we can abort all pending (not commited) transaction which helps us simulate a scenario where our transactions are dropped from the transaction pool.

Use a SimulateBackend for thorough testing

Now our journey comes to an end. We have learned how to

  • connect to an Ethereum node
  • call basic functions to get blocks or transactions from the blockchain
  • create go-bindings for your smart contracts using abigen
  • deploy and connect to your contracts.
  • filter for past events, and
  • listen to new events from our contracts.

And in this part we learned how to mock a blockchain to test your contracts.

If you have any questions about web3.go or any of the topics discussed in this tutorial, please reach out to me! @vdWijden on Twitter.

Part1: Connecting and sending transactions
Part2: Calling functions on smart contracts
Part3: Listening on events from smart contracts
Part4: Creating a mock-blockchain for testing

If you want to get in touch, just message me at @vdWijden on twitter or Linkedin.

--

--

Marius Van Der Wijden

Ethereum Developer, State Channel Researcher, Student at TU Darmstadt