Intro to Web3.go Part 4: Testing
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).
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
.
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.
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.