#Testing with Web3.js & Truffle
TIP
Read this guide to learn about our recommended approach to testing contracts.
Hardhat allows you to use Truffle to test your smart contracts. This mainly means compatibility with the @truffle/contract
package to interact with your smart contracts.
Truffle 4 and Truffle 5 are supported using the @nomiclabs/hardhat-truffle4
and @nomiclabs/hardhat-truffle5
plugins respectively.
Let's see how to do this creating a new Hardhat project.
Run these to start:
mkdir my-project
cd my-project
npm init --yes
npm install --save-dev hardhat
Now run npx hardhat init
inside your project folder and select Create an empty hardhat.config.js
.
Let's now install the Truffle
and Web3.js
plugins, as well as web3.js
itself.
npm install --save-dev @nomiclabs/hardhat-truffle5 @nomiclabs/hardhat-web3 'web3@^1.0.0-beta.36'
Enable the Truffle 5 plugin on your Hardhat config file by requiring it:
require("@nomiclabs/hardhat-truffle5");
module.exports = {
solidity: "0.7.3"
};
Create a folder named contracts
inside your project. Add a file named Greeter.sol
, and copy and paste this code:
pragma solidity ^0.7.0;
contract Greeter {
string greeting;
constructor(string memory _greeting) {
greeting = _greeting;
}
function greet() public view returns (string memory) {
return greeting;
}
function setGreeting(string memory _greeting) public {
greeting = _greeting;
}
}
# Writing a test
Create a new directory called test
inside your project root directory and create a new file called Greeter.js
.
Let's start with the code below. We'll explain it next, but for now paste this into Greeter.js
:
const Greeter = artifacts.require("Greeter");
// Traditional Truffle test
contract("Greeter", (accounts) => {
it("Should return the new greeting once it's changed", async function () {
const greeter = await Greeter.new("Hello, world!");
assert.equal(await greeter.greet(), "Hello, world!");
await greeter.setGreeting("Hola, mundo!");
assert.equal(await greeter.greet(), "Hola, mundo!");
});
});
// Vanilla Mocha test. Increased compatibility with tools that integrate Mocha.
describe("Greeter contract", function () {
let accounts;
before(async function () {
accounts = await web3.eth.getAccounts();
});
describe("Deployment", function () {
it("Should deploy with the right greeting", async function () {
const greeter = await Greeter.new("Hello, world!");
assert.equal(await greeter.greet(), "Hello, world!");
const greeter2 = await Greeter.new("Hola, mundo!");
assert.equal(await greeter2.greet(), "Hola, mundo!");
});
});
});
As you can see in the first line, the artifacts object is present in the global scope and you can use it to access the Truffle contract abstractions.
const Greeter = artifacts.require("Greeter");
These examples show two approaches towards testing:
- Using
contract()
, which is the traditional way to test with Truffle - Using
describe()
, which is the traditional way to test using Mocha
Truffle runs its tests with Mocha, but a few tools that integrate Mocha don't expect contract()
and don't always work well. We recommend using the describe()
approach.
You can run these tests by running npx hardhat test
:
$ npx hardhat test
Contract: Greeter
✓ Should return the new greeting once it's changed (265ms)
Greeter contract
Deployment
✓ Should deploy with the right greeting (114ms)
2 passing (398ms)
If you want to use Truffle Migrations to initialize your tests and call deployed()
on the contract abstractions, both @nomiclabs/hardhat-truffle4
and @nomiclabs/hardhat-truffle5
offer a fixtures feature to make this possible. Take a look at the Truffle migration guide to learn more.
# Using Web3.js
To use Web3.js in your tests, an instance of it is available in the global scope. You can see this in the describe()
test in Greeter.js
:
const Greeter = artifacts.require("Greeter");
// Traditional Truffle test
contract("Greeter", accounts => {
it("Should return the new greeting once it's changed", async function() {
const greeter = await Greeter.new("Hello, world!");
assert.equal(await greeter.greet(), "Hello, world!");
await greeter.setGreeting("Hola, mundo!");
assert.equal(await greeter.greet(), "Hola, mundo!");
});
});
// Vanilla Mocha test. Increased compatibility with tools that integrate Mocha.
describe("Greeter contract", function() {
let accounts;
before(async function() {
accounts = await web3.eth.getAccounts();
});
describe("Deployment", function() {
it("Should deploy with the right greeting", async function() {
const greeter = await Greeter.new("Hello, world!");
assert.equal(await greeter.greet(), "Hello, world!");
const greeter2 = await Greeter.new("Hola, mundo!");
assert.equal(await greeter2.greet(), "Hola, mundo!");
});
});
});
Checkout the plugin's README file for more information about it.