Skip to content

Write JavaScript tests

TronBox uses the Mocha testing framework and Chai for assertions to provide you with a solid framework from which to write your JavaScript tests. Let's dive in and see how TronBox builds on top of Mocha to make testing your contracts a breeze.

TIP

NOTE: If you're unfamiliar with writing unit tests in Mocha, please see Mocha's documentation before continuing.

Use contract() instead of describe()

Structurally, your tests should remain largely unchanged from those of Mocha: Your tests should exist in the ./test directory, they should end with a .js extension, and they should contain code that Mocha will recognize as an automated test. What makes TronBox tests different from those of Mocha is the contract() function.

contract() behaves just like Mocha's describe(), but adds two conveniences for contract testing:

  • It passes an accounts array — the addresses available on the current TRON network — into your test callback.
  • It raises the default per-test timeout to 300 seconds, which suits on-chain calls and deployments.

Your migrations deploy your contracts before the tests start, and the whole suite runs against that live deployment. State accumulates as the tests run — anything one test changes is visible to the tests that follow — so create a fresh instance with MyContract.new() when a test needs isolation, or order your tests around the shared state.

Use contract abstractions within your tests

Contract abstractions are the basis for making TRON contract interaction possible from JavaScript. Because TronBox has no way of detecting which contracts you'll need to interact with, you'll need to ask for those contracts explicitly. You do this by using the artifacts.require() method, a method provided by TronBox that allows you to request a usable contract abstraction for a specific Solidity contract. As you'll see in the example below, you can then use this abstraction to make sure your contracts are working properly. For more information on using contract abstractions see the Interact with contracts section.

Using artifacts.require()

Using artifacts.require() within your tests works the same way as using it within your migrations; you just need to pass the name of the contract. See the artifacts.require() documentation in the Migrations section for detailed usage.

Using tronWrap

A tronWrap instance is available in each test file, which can be referenced directly. So calling tronWrap.trx.getBalance(account) just works!

Examples

Here's an example test provided in the MetaCoin TronBox Box using async/await notation. Note the use of the contract() function, the accounts array for specifying available TRON accounts, and our use of artifacts.require() for interacting directly with our contracts.

Filename: ./test/metacoin.js

JavaScript
javascript
const MetaCoin = artifacts.require('MetaCoin');

contract('MetaCoin', async accounts => {
  it('should put 10000 MetaCoin in the first account', async () => {
    let instance = await MetaCoin.deployed();
    let balance = await instance.getBalance(accounts[0]);
    assert.equal(balance.valueOf(), 10000);
  });

  it('should call a function that depends on a linked library', async () => {
    let meta = await MetaCoin.deployed();
    let outCoinBalance = await meta.getBalance(accounts[0]);
    let metaCoinBalance = Number(outCoinBalance);
    let outCoinConvertedBalance = await meta.getConvertedBalance(accounts[0]);
    let metaCoinConvertedBalance = Number(outCoinConvertedBalance);
    assert.equal(metaCoinConvertedBalance, 2 * metaCoinBalance);
  });

  it('should send coin correctly', async () => {
    // Get initial balances of first and second account.
    let account_one = accounts[0];
    let account_two = accounts[1];

    let amount = 10;

    let instance = await MetaCoin.deployed();
    let meta = instance;

    let balance = await meta.getBalance(account_one);
    let account_one_starting_balance = Number(balance);

    balance = await meta.getBalance(account_two);
    let account_two_starting_balance = Number(balance);
    await meta.sendCoin(account_two, amount, { from: account_one });

    balance = await meta.getBalance(account_one);
    let account_one_ending_balance = Number(balance);

    balance = await meta.getBalance(account_two);
    let account_two_ending_balance = Number(balance);

    assert.equal(
      account_one_ending_balance,
      account_one_starting_balance - amount,
      "Amount wasn't correctly taken from the sender"
    );
    assert.equal(
      account_two_ending_balance,
      account_two_starting_balance + amount,
      "Amount wasn't correctly sent to the receiver"
    );
  });
});

Execute the tests:

Terminal
shell
tronbox test

This test will produce the following output:

Terminal
shell
Using network 'development'.

Deploying contracts to development network...
Preparing Javascript tests (if any)...


  Contract: MetaCoin
 should put 10000 MetaCoin in the first account
 should call a function that depends on a linked library (68ms)
 should send coin correctly (137ms)


  3 passing (240ms)

Specifying tests

You can limit the tests to a specific file in the test directory as shown below:

Terminal
shell
tronbox test ./test/metacoin.js

For more information, please see the Command line options.