Writing Unit Tests in Hardhat for Solidity Smart Contracts

Hardhat is a popular development environment for Ethereum, offering a suite of tools that streamline the process of smart contract development. One of its most valuable features is the built-in support for unit testing. Properly testing your smart contracts is crucial to ensure their functionality and security. In this guide, we'll delve deep into how to write unit tests in Hardhat, using a practical example for clarity.

sequenceDiagram participant Developer participant Hardhat participant Smart Contract Developer->>Hardhat: Initialize project Hardhat->>Developer: Provide sample contract & test Developer->>Hardhat: Write unit test Hardhat->>Smart Contract: Deploy contract Hardhat->>Smart Contract: Run tests on contract Smart Contract->>Hardhat: Return test results Hardhat->>Developer: Display test results

Setting Up Your Hardhat Environment

Before diving into the unit tests, ensure you have a Hardhat project set up. If you're new to Hardhat, you can quickly initialize a new project using:

Bash
npx hardhat init

This command sets up a basic Hardhat project structure, including a sample contract and test.

The Sample Contract: Web3NFT

For this guide, let's consider the following smart contract, which is an NFT contract built using OpenZeppelin's libraries:

Solidity
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";

contract Web3 is ERC721URIStorage {
    uint256 Web3_Token_ID;

    constructor() ERC721("Web3NFT", "Web3N") {}

    function mintNFT(
        address _userOne,
        address _userTwo,
        string memory tokenURI
    ) public {
        _mint(_userOne, Web3_Token_ID);
        _setTokenURI(Web3_Token_ID, tokenURI);
        Web3_Token_ID++;

        _mint(_userTwo, Web3_Token_ID);
        _setTokenURI(Web3_Token_ID, tokenURI);
        Web3_Token_ID++;
    }
}

This contract allows for minting NFTs and assigning them a unique URI.

Writing the Unit Test

Preliminary Checks

Before minting the NFTs, it's essential to establish some baseline checks:

  1. Ensure that the Web3_Token_ID is initialized to 0.
  2. Confirm that the balances of _userOne and _userTwo are 0.

The Test Structure

Using Hardhat's testing framework, the structure for our test would look something like this:

JavaScript
const { expect } = require("chai");
const { ethers } = require("hardhat");

describe("Web3NFT Contract", function () {
    let Web3NFT, web3nft, owner, userOne, userTwo;

    beforeEach(async function () {
        Web3NFT = await ethers.getContractFactory("Web3");
        [owner, userOne, userTwo, ...addrs] = await ethers.getSigners();
        web3nft = await Web3NFT.deploy();
        await web3nft.deployed();
    });

    describe("Minting NFTs", function () {
        it("Should mint NFTs correctly", async function () {
            expect(await web3nft.Web3_Token_ID()).to.equal(0);
            expect(await web3nft.balanceOf(userOne.address)).to.equal(0);
            expect(await web3nft.balanceOf(userTwo.address)).to.equal(0);

            await web3nft.mintNFT(userOne.address, userTwo.address, "sampleURI");

            expect(await web3nft.Web3_Token_ID()).to.equal(2);
            expect(await web3nft.balanceOf(userOne.address)).to.equal(1);
            expect(await web3nft.balanceOf(userTwo.address)).to.equal(1);
        });
    });
});

Running the Test

To execute the test, use the following command:

Bash
npx hardhat test

This will run the test, and if everything is set up correctly, you should see the test pass.

FAQs

Q: What is Hardhat?
A: Hardhat is a development environment for Ethereum, offering tools for smart contract development, including unit testing.

Q: Why is unit testing important for smart contracts?
A: Unit testing ensures the functionality and security of smart contracts, helping to identify and rectify potential issues.

Q: How do I run tests in Hardhat?
A: Use the command npx hardhat test to execute your unit tests in a Hardhat project.

Author