5

I am using Hardhat to deploy and test my smart contract on RSK testnet. This is the hardhat.config.js setup I am using:

require('@nomiclabs/hardhat-waffle');

const mnemonic = fs.readFileSync('.mnemonic', 'utf8').toString().trim();
const minimumGasPriceTestnet = 65164000;
const TESTNET_GAS_MULT = 1;
module.exports = {
  solidity: '0.7.3',
  defaultNetwork: 'rsktestnet',
  networks: {
    hardhat: {},
    rsktestnet: {
      chainId: 31,
      url: 'https://public-node.testnet.rsk.co/',
      gasPrice: Math.floor(minimumGasPriceTestnet * TESTNET_GAS_MULT),
      gasMultiplier: TESTNET_GAS_MULT,
      accounts: {
        mnemonic,
        initialIndex: 0,
        count: 10,
      },
    },
  },
};

Unfortunately, my tests fail and I receive the following error message:

Error: Timeout of 20000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/Users/ales/Work/IOV/demo-code-snippets/hardhat-tutorial/ethers-waffle/test/Token.js)
          at listOnTimeout (internal/timers.js:554:17)
          at processTimers (internal/timers.js:497:7)

What is the problem here? What does done() referring to here?

bguiz
  • 27,371
  • 47
  • 154
  • 243
Irene Patrikios
  • 249
  • 1
  • 5

2 Answers2

5

Since you are deploying to a public blockchain network, need to take into account the block mining interval. On the RSK network, this takes around 30s. Mocha, which is the test runner framework used by hardhat, fails when tests take longer than 20s.

The solution is to configure Mocha to use a longer timeout value, before it fails tests for taking too long. Here's the reference hardhat config documentation.

Add the following lines to your hardhat.config.js, if you wish to set a timeout of, for example, 10 minutes (60000ms).

mocha: {
    timeout: 600000,
},

And the full hardhat.config.js file should look as follows:

module.exports = {
  solidity: '0.7.3',
  defaultNetwork: 'rsktestnet',
  networks: {
    rsktestnet: {
      chainId: 31,
      url: 'https://public-node.testnet.rsk.co/',
      gasPrice: Math.floor(minimumGasPriceTestnet * TESTNET_GAS_MULT),
      gasMultiplier: TESTNET_GAS_MULT,
      accounts: {
        mnemonic,
        initialIndex: 0,
        count: 10,
      },
    },
  },
  mocha: {
    timeout: 600000,
  },
};
Aleks Shenshin
  • 2,117
  • 5
  • 18
3

The previous answer configures hardhat such that you can set the default timeout for all tests. This may be sufficient in some cases; however in others, we may need to vary the duration allowed with higher granularity.

To do this, use this.timeout() within describe blocks or it blocks. For example:

describe('(1) my group of test with no blockchain interactions', function () {
    it('(1a) my simple test', function() {
        // this gets 2s (the mocha default)
    });
});

describe('(2) my group of rsk tests', function () {
    // each `it` block within this describe block gets 35s
    this.timeout(35e3); 

    it('(2a) my rsk test with 1 transaction', function() {
        // this gets 35s
    });

    it('(2b) my rsk test with 3 transactions', function() {
        this.timeout(105e3); 
        // this gets 105s
    });
});

In the above example, we have:

(1) the first describe block.

(1a) the it test gets the default mocha timeout of 2s.

(2) the second describe block, which configures a custom timeout of 35s.

(2a) the first it test, which "inherits" the 35s custom timeout from its parent describe block.

(2b) the second it test, which "overrides" the 35s custom timeout from its parent describe block, and instead sets its own 105s custom timeout.

bguiz
  • 27,371
  • 47
  • 154
  • 243