jest icon indicating copy to clipboard operation
jest copied to clipboard

test.concurrent ignores beforeEach and afterEach

Open sibyldawn opened this issue 6 years ago • 18 comments

🐛 Bug Report

When using test.concurrent with tests, all the scenarios run first and then the beforeEach and afterEach blocks run next.

To Reproduce

Write a simple test suite with a beforeEach , 3 tests using test.concurrent, and afterEach.

Expected behavior

I expect runner to execute beforeEach block, then the test, then afterEach block.

Link to repl or repo (highly encouraged)

test-concurrent bug demo

Issues without a reproduction link are likely to stall.

Run npx envinfo --preset jest

Paste the results here:

Jest v22.1.2 node v7.4.0 linux/amd64
   
 PASS  ./concurrent-test.js
  try running parallel by scenario level
    ✓ First Test (3ms)
    ✓ Second Test
    ✓ Third Test (1ms)

  console.log concurrent-test.js:8
    Test 1

  console.log concurrent-test.js:12
    Test 2

  console.log concurrent-test.js:16
    Test 3

  console.log concurrent-test.js:4
    BEFORE

  console.log concurrent-test.js:20
    AFTER

  console.log concurrent-test.js:4
    BEFORE

  console.log concurrent-test.js:20
    AFTER

  console.log concurrent-test.js:4
    BEFORE

  console.log concurrent-test.js:20
    AFTER

Test Suites: 1 passed, 1 total
Tests:       3 passed, 3 total
Snapshots:   0 total
Time:        0.993s, estimated 1s
Ran all test suites.
   

sibyldawn avatar Feb 26 '19 21:02 sibyldawn

https://github.com/facebook/jest/issues/4281 dupliacted issue it would be very nice if jest fix it

luxflow avatar Feb 27 '19 07:02 luxflow

Think this is the RCA

jest-circus

https://github.com/facebook/jest/blob/c9c8dba4dd8de34269bdb971173659399bcbfd55/packages/jest-circus/src/legacy-code-todo-rewrite/jestAdapterInit.ts#L84-L90

jest-jasmine https://github.com/facebook/jest/blob/c9c8dba4dd8de34269bdb971173659399bcbfd55/packages/jest-jasmine2/src/jasmineAsyncInstall.ts#L172-L176

Mark1626 avatar Aug 14 '20 17:08 Mark1626

@SimenB It seems easy to change the workflow in jest-circus to fix this, I've made a POC. Let me know if this approach would be a good solution

Mark1626 avatar Aug 14 '20 18:08 Mark1626

But not sure if Before and After make sense for test.concurrent, if I perform a stateful operation in the hooks then the tests will be indeterministic

Mark1626 avatar Aug 14 '20 18:08 Mark1626

@Mark1626 beforeEach and afterEach might not make a ton of sense for test.concurrent, but beforeAll and afterAll would I think.

csojinb avatar Aug 21 '20 19:08 csojinb

@SimenB bump

Mark1626 avatar Sep 23 '20 03:09 Mark1626

Please fix.

joshuambg avatar Oct 14 '20 21:10 joshuambg

Looks like adding an empty not concurrent test before concurrent ones fixes the issue. At least with beforeAll.

UPD: no, this doesn't work :/

SpadarShut avatar Jan 07 '21 19:01 SpadarShut

Looks like adding an empty not concurrent test before concurrent ones fixes the issue. At least with beforeAll.

How did you set up your test suite? I have something like the following which is not working:

describe('...', () => {
  beforeAll(async () => {
    // do some setup
  });

  afterAll(async () => {
    // do teardown
  });

  it('noop', () => {
    expect(2+2).toBe(4);
  });

  it.concurrent('...', async () => {
    // runs before beforeAll
  });

  it.concurrent('...', async () => {
    // runs before beforeAll
  });
});

rhyek avatar Mar 11 '21 17:03 rhyek

Looks like adding an empty not concurrent test before concurrent ones fixes the issue. At least with beforeAll.

How did you set up your test suite? I have something like the following which is not working:

I ended up just running the async preparation code in the test file before describe block. I guess this is not ideal, though.

Another workaround is to make a promise which resolves after setup is ready and await for it in every concurrent test:

let beforeAllResolve;

const beforeAllPromise = new Promise((resolve) => {
  beforeAllResolve = resolve;
});

describe('...', () => {
  beforeAll(async () => {
    // do some setup
    // RESOLVE
    beforeAllResolve()
  });

  afterAll(async () => {
    // do teardown
  });

  it.concurrent('...', async () => {
     await beforeAllPromise;
     // do stuff
  });

  it.concurrent('...', async () => {
     await beforeAllPromise;
     // do stuff
  });
});

SpadarShut avatar Mar 11 '21 18:03 SpadarShut

Has there been any progress on this? Would prefer not to rework hundreds of lines of tests 😅

benminer avatar Jan 14 '22 21:01 benminer

The issue still persists. I regret I recommended our team to use Jest when test.concurrent does not support .beforeAll() and .afterAll() aren't working as expected. This should be a high priority issue.

igor-q-bio avatar Jun 25 '22 00:06 igor-q-bio

I found some workaround to execute beforeAll before test.concurrent. Seems like the problem is not with test.concurrent logic but with describe. If we move beforeAll out from describe, everything works as expected:

let str;

beforeAll(() => {
   str = 'Some str with number 3';
});

describe('describe description', () => {
   test.concurrent('concurrent tests', () => {
      expect(str).toBe(`Some str with number ${Math.floor(Math.random() * 5) + 1}`);
   });
});

But beforeEach and afterEach still are ignored. Even those, that are in setupFiles or setupFilesAfterEnv configuration files...

RomanShmandrovskyi avatar Mar 05 '23 10:03 RomanShmandrovskyi

afterEach makes sense for us, because this is here we do screenshots for failed test.

gladykov avatar Jan 16 '24 14:01 gladykov

I spawn in BeforeEach my testcontainer and stop it in after each. Thought test.concurrent would work as no test has a shareable state till i found out that it wont even wait for the container start...

Sure i could put it inside everytest, but i would love something so i dont have to write the same thing in 30 tests each file if there would be something like beforeEach ...

ScriptType avatar Nov 04 '24 08:11 ScriptType

This issue is stale because it has been open for 1 year with no activity. Remove stale label or comment or this will be closed in 30 days.

github-actions[bot] avatar Nov 04 '25 09:11 github-actions[bot]

activity

Bessonov avatar Nov 04 '25 10:11 Bessonov

Hello there. When working on #15825, I questioned myself on the exact meaning of before/after each hooks in the context of concurrent tests. I had an idea using async local storages provided to hooks, but I am worried it would add complexity that would be better managed in the user code directly. For example, I imagined something like this:

describe('concurrent tests', () => {
  beforeEach(async asyncContext => {
    asyncContext.set(await initDb())
  })
  afterEach(async asyncContext => {
    asyncContext.get().dispose()
  })
  test.concurrent(dbInstance => { // The value set in `asyncContext`
    dbInstance.query(...)
  })
})

There may be a lot of alternatives on how to provide async local storage containers/values in which function, but the fact that test.concurrent would not be a 0-ary fn is already quite a change.

Is it something that could address user's issues on that area ?

GerkinDev avatar Nov 04 '25 13:11 GerkinDev