In Jest, is there any way to get a beforeAll/beforeEach block to run prior to assertions when using a function to generate describe/it blocks?

Viewed 3175

When using a function to generate describe/it blocks that are used often within a test file, beforeAll or beforeEach blocks that exist in a parent describe are ignored.

For example:

const repeatedTests = (num) => {
  // DOES NOT WORK - num is undefined
  describe(`Testing number ${num}`, () => {
    it('should exist', () => {
      expect(num).toBeDefined();
    });
    it('should be a number', () => {
      expect(num).not.toBeNaN();
    });
    it('should be less than 5', () => {
      expect(num).toBeLessThan(5);
    });
  });
};

describe.each([[1],[2],[3]])('Describe for %i', (num) => {
  let numForTesting;
  beforeAll(() => {
    numForTesting = num;
  });
  repeatedTests(numForTesting);
});

I understand why this is the case - repeatedTests will run immediately, as it is not a describe/it that the test runner is watching out for.

In order to get this to work, I need to do something like this:

const repeatedTests = (num) => {
  describe(`Testing number ${num}`, () => {
    let numForTesting;
    beforeAll(() => {
      numForTesting = num;
    });
    it('should exist', () => {
      expect(numForTesting).toBeDefined();
    });
    it('should be a number', () => {
      expect(numForTesting).not.toBeNaN();
    });
    it('should be less than 5', () => {
      expect(numForTesting).toBeLessThan(5);
    });
  });
};

describe.each([[1],[2],[3]])('Describe for %i', (num) => {
  repeatedTests(num);
});

In the particular testing suite that I'm working on (which is far more complex than this, in case that isn't obvious) - doing things this way makes things quite tricky, and makes reusing a generator function really challenging.

Is there any way to have a beforeAll or beforeEach run before a testing block that's generated inside of a function, a la my original example?

For what it's worth, the equivalent of setting num in my simple example above is mounting a react node using enzyme.

1 Answers

Is there any way to have a beforeAll or beforeEach run before a testing block that's generated inside of a function, a la my original example?

For the reason you mentioned, my sense is that the answer is no.

Here is a different approach that might do what you need. It uses a generateState function instead of a jest hook.

const repeatedTests = (generateState) => {

    const num = generateState();

    describe(`Testing number ${num}`, () => {
        it('should exist', () => {
            expect(num).toBeDefined();
        });
        it('should be a number', () => {
            expect(num).not.toBeNaN();
        });
        it('should be less than 5', () => {
            expect(num).toBeLessThan(5);
        });
    });
};

describe.each([[1], [2], [3]])('Describe for %i', (num) => {

    const generateState = () => {
        return num;
    }

    repeatedTests(generateState);
});

This is the test output:

 PASS  ./index.test.js
  Describe for 1
    Testing number 1
      √ should exist (4ms)
      √ should be a number (1ms)
      √ should be less than 5
  Describe for 2
    Testing number 2
      √ should exist
      √ should be a number
      √ should be less than 5 (1ms)
  Describe for 3
    Testing number 3
      √ should exist
      √ should be a number (1ms)
      √ should be less than 5
Related