Jest or Mocha: Dynamically create tests based on async initialization

Viewed 1767

I'm trying to generate tests dynamically by looping over an array returned from an async call. I just cannot figure out how to do this - either using mocha or using jest. To illustrate using code, the following synchronous example works:

describe("Test using various frameworks", () => {
    ["mocha", "jest"].forEach(framework => {
        it(`Should test using ${framework}`, () => {
            expect(true).toBe(true);
        });
    });
});

However, if that array is fetched asynchronously, I cannot get the testing frameworks to wait until the array is fetched before trying to loop over it.

async function getFrameworks() {
    //TODO: get it from some async source here
    return ["mocha", "jest"];
}

describe("Test using various frameworks", () => {
    var frameworks;
    //before() instead of beforeAll() if using mocha
    beforeAll(async ()=> {
        frameworks = await getFrameworks();
    });

    frameworks.forEach(framework => {
        it(`Should test using ${framework}`, () => {
            expect(true).toBe(true);
        });
    });
});

This fails saying Cannot read property 'forEach' of undefined. I've tried all sort of combinations of using async/await and Promise and passing in a done callback but to no avail.

The closest I came to this was using Mocha's --delay flag, but that only solves part of the problem. What I really want to do in my actual use case is to run some async intialization in the before() or beforeAll() hooks which I then use to dynamically generate tests.

Any pointers on how to do this using either mocha or jest?

2 Answers

Mocha has some support async tests. Specifically, your it() callback can be async. Here is how to rearrange your tests to "looping over an array returned from an async call":

const chai = require('chai');
const { expect } = require('chai');

function getMyTestData() {
  return new Promise(resolve => setTimeout(() => resolve(['mocha', 'jest']), 1000));
}

describe('Test using various frameworks', () => {
  it('Should test by looping over an array returned from an async call', async () => {
    const myTestData = await getMyTestData();
    for(let datum of myTestData) {
      expect(datum.length).greaterThan(4, `Data '${datum}' not long enough`);
    }
  })
});
Related