These asserting functions are called "matchers", and the ones we're using here actually come from Waffle. Check out this section in Waffle's documentation for the entire list of Ethereum-specific matchers. If you're making a call or sending a transaction, make sure to check Waffle's documentation, and await these Promises. Otherwise your tests may pass without waiting for all checks to complete. Interacting with the Ethereum network and smart contracts are asynchronous operations, hence most APIs and libraries use JavaScript's Promise for returning values.
This use of async will allow us to await the calls to our contract and the Hardhat Network node. This is the object that has a method for each of your smart contract functions. Here we're passing the string Hello, world! Once the contract is deployed, we can call our contract methods on greeter and use them to get the state of the contract. To do this we're using the Chai matchers expect, to and equal. Let's dive in and see how Truffle builds on top of Mocha to make testing your contracts a breeze.
Note: If you're unfamiliar with writing unit tests in Mocha, please see Mocha's documentation before continuing. What makes Truffle tests different from that of Mocha is the contract function: This function works exactly like describe except it enables Truffle's clean-room features. It works like this: Before each contract function is run, your contracts are redeployed to the running Ethereum client so the tests within it run with a clean contract state.
The contract function provides a list of accounts made available by your Ethereum client which you can use to write tests. Since Truffle uses Mocha under the hood, you can still use describe to run normal Mocha tests whenever Truffle clean-room features are unnecessary. Because Truffle has no way of detecting which contracts you'll need to interact with within your tests, you'll need to ask for those contracts explicitly. You do this by using the artifacts.
To achieve this, Software Engineers need some framework that can maintain the test suites, run the test scripts and populate the test results. It makes asynchronous testing simpler. It provides accurate test reports and the stack trace of any uncaught exceptions. In other hand Chai is an assertion library we can pair with any JavaScript testing framework.
Source code: In this entire article, whatever examples we are going to discuss is available on the GitHub repository. For a better understanding, please clone the repository link and follow the below instructions Agenda: In this article, we will discuss the below topics. Setup Mocha Understanding a TDD based basic mocha spec Understanding the actual code execution with mocha Brief discussion on Hooks Managing test suite in mocha Getting started with Chai Testing Promises with Chai Mocha Reporter Prerequisite: Before starting with mocha, make sure that your machine should have node and npm installed.
You can install the node LTS version from the nodejs website, and npm will install automatically with node. To check the versions of the installed node and npm, run the below commands. Note: Mocha is compatible with Node. It determines the test failure. And It has two parameters, the first one is the meaningful name that describes the functionality under the method, and the second one is the function which basically contains one or multiple tests. It has two parameters as well, the first one is the meaningful name of the test and the second one is the function that contains the body or steps of the test.
Note: Commands called mocha test, or only mocha, can also be used to run the test specs. Once the execution gets completed, you will see the below output on the console. Understanding the actual code execution with mocha In this section, we will discuss actual code execution with mocha, where we will see how mocha can perform test execution for various kinds of functions in JavaScript.
Testing a function with mocha: Every function holds some specific instructions to complete specific tasks. And to test those tasks, the defined function needs to be a call from mocha specs along with required input parameters if applicable. Snapshot 1, the function which needs to be tested Snapshot 2, mocha test spec to test the function Testing Asynchronous function using mocha : The basic difference between asynchronous function testing with mocha is that we need to tell mocha once the test gets completed because of the async nature of function under test.
So, we need to define a callback i. The Asynchronous function which needs to be tested Mocha specs to test asynchronous function Hooks Understanding: We might need to execute a few of our codes before or after the actual business logic validation. You can use Hooks to set up preconditions and clean up after the test execution. It describes each test step with valid step definitions, which helps identify errors quickly.
The function will receive the value as its input, but it need not use it. The most simple case asserts that a revert happened: await expect contract. The revertedWith matcher allows you to assert that a revert's error data does or doesn't match a specific string: await expect contract.
The revertedWithCustomError matcher allows you to assert that a transaction reverted with a specific custom error : await expect contract. If you're expecting an error from a nested call to a different contract, then you'll need to pass that different contract as the first argument. Further, just as events can have arguments, so too can custom error objects, and, just as with events, you can assert the values of these arguments.
To do this, use the same. Contracts returning integer values can yield numbers greater than JavaScript's maximum safe integer value, and writing assertions about the expectations of such values can be difficult without prior familiarity with the 3rd-party big integer library used by your web3 framework.
This package enhances the standard numerical equality matchers equal, above, within, etc such that you can seamlessly mix and match contract return values with regular Numbers.
Once the execution gets completed, you will see the below output on the console. Understanding the actual code execution with mocha In this section, we will discuss actual code execution with mocha, where we will see how mocha can perform test execution for various kinds of functions in JavaScript. Testing a function with mocha: Every function holds some specific instructions to complete specific tasks. And to test those tasks, the defined function needs to be a call from mocha specs along with required input parameters if applicable.
Snapshot 1, the function which needs to be tested Snapshot 2, mocha test spec to test the function Testing Asynchronous function using mocha : The basic difference between asynchronous function testing with mocha is that we need to tell mocha once the test gets completed because of the async nature of function under test.
So, we need to define a callback i. The Asynchronous function which needs to be tested Mocha specs to test asynchronous function Hooks Understanding: We might need to execute a few of our codes before or after the actual business logic validation. You can use Hooks to set up preconditions and clean up after the test execution.
It describes each test step with valid step definitions, which helps identify errors quickly. Hooks will run in their order they are defined. Output of the above spec looks like below Managing test suite in mocha In this section, we will discuss test suite management in mocha.
Sometimes it may require running only a few specific test specs or suites instead of running all at a time, or we may want to skip some specific test specs or suites during execution that we can achieve in mocha. The output of the above mocha specs shows up below.
From the output, we can see mocha. Getting Started with Chai In the introduction, we have got a sight of Chai assertion library. Chai provides an expressive and readable style of writing test followed by BDD, which is helpful to understanding the test flow and actual validation point. Installation of Chai Installation: Before starting with the examples, We have to install Chai into the system. So, to install chai, run the below command on the command prompt. BDD style comes in two flavors.
Expect: Expect is one of the interfaces by which BDD style is exposed in chai. Users can chain together natural language assertions. Refer to the example below. It works on node. The most simple case asserts that a revert happened: await expect contract.
The revertedWith matcher allows you to assert that a revert's error data does or doesn't match a specific string: await expect contract. The revertedWithCustomError matcher allows you to assert that a transaction reverted with a specific custom error : await expect contract.
If you're expecting an error from a nested call to a different contract, then you'll need to pass that different contract as the first argument. Further, just as events can have arguments, so too can custom error objects, and, just as with events, you can assert the values of these arguments. To do this, use the same.
Contracts returning integer values can yield numbers greater than JavaScript's maximum safe integer value, and writing assertions about the expectations of such values can be difficult without prior familiarity with the 3rd-party big integer library used by your web3 framework. This package enhances the standard numerical equality matchers equal, above, within, etc such that you can seamlessly mix and match contract return values with regular Numbers. For example: expect await token.