Hardhat Testing – How to Use Promises in Loop Contract Calls

hardhattestingtypescript

I've written this test but I've been told here that I should not use await inside a for loop; What I've found out is that using await will stop the execution of my code until the call to the network is finished which in some cases is something undesirable;

My problem is that when I use promises I get the following assertion error

AssertionError: expected Promise{…} to equal +0

and when I use await my test pass; I understand that when I use the promise method, the call is not finished yet when I try to compare to the expected value '0'

My question is: How to properly write this test using promises?

//Can loop transaction with a new signer
for (let foo = 0; foo < 100; foo++) {
  //With Promise </3
  expect(contract.connect(signers[foo]).balanceOf(signers[foo].address, 1)
    .then(response => {
      return response.toNumber();
    })
    .catch(err => console.log(err))).to.be.equal(0);

  //With Await <3   
  expect(await contract.connect(signers[foo])
    .balanceOf(signers[foo].address, 1)).to.be.equal(0);
}

I think its important knowing this because it can help you plan your tests better

Best Answer

I found an answer, I should've used Promise.all as the guy mention in the question here, i get the promise code snippet from here, thanks to @Mavcom.ETH for guiding me here

The difference between Promise.all and Await inside a for loop is that looping in execution time, it will stop and await until the call is done to continue the loop in contrast to the promise.all which does all the calls and wait for them asynchronously which can be faster if the order of the calls doesn't matter

        let signers: Wallet[] = [];
    
        //create 100 wallets
        for (let i = 0; i < 100; i++) {
          //create a new wallet
          let wallet = ethers.Wallet.createRandom().connect(ethers.provider);
          //can store as signer
          signers.push(wallet);
          //can store as address
          addressArray.push(wallet.address.toString());
        }
    
        const checkTheirNFT = () => {
          return Promise.all(
            signers.map(async fooSigner => {
              expect(await yourNFTContract.connect(fooSigner).balanceOf(fooSigner.address, 1)).to.be.equal(0);
              console.log(`fooWallet: ${fooSigner.address}`);
            })
          ).then(() => {
            console.log("done");
          });
        };
        await checkTheirNFT();

      });
Related Topic