Jest’s ‘beforeEach’ may not be running the way you think it does…
For the last few years I’ve been a pretty heavy user of Jest, I use it as my test runner across both my FE and BE stacks. While I’m a daily driver of the framework I was recently very surprised to discover a situation where one of my assumptions of how it runs, particularly the order of its beforeEach
method was totally incorrect.
Let’s start with an ordinary jest test describe:
Fairly standard. The beforeAll
will run first, followed by a beforeEach
prior to each test running, resulting with the output of:
top level before all
top level before each
top level test 1
top level before each
top level test 2
No surprises there.
Now what if we added a level of nesting within that test. Say there was another describe block with its own series of tests that all require the same beforeEach
setup and a common beforeAll
setup. Jest supports this behaviour, although it is something that I don’t use often:
Now what I assumed would run here would be the same behaviour as before:
The top-beforeAll
running first, the top-beforeEach
running before each test and then once before the describe block.
Then the nested-beforeAll
and the nested-beforeEach
before each test within the describe block. That assumption was wrong.
// as expected
top level before all
top level before each
top level test 1
top level before each
top level test 2// wait what, you're running a bit early!
nested before all
top level before each
nested before each
nested test 1// hang on, why is this running again?
top level before each
nested before each
nested test 2
What I had incorrectly assumed was the beforeEach
call would apply to the describe block in the same way it does with a test block: run once before the inner content of the block, regardless of it being a test or a describe. The actual situation totally different:
It will run before each test even if they are nested. So while I was expecting the top-beforeEach
to have run 3 times total, once for each method within its block, it actually runs 4 times!
The other behaviour here to consider is that the nested-beforeAll
actually runs before the top-beforeEach
, meaning that if your nested-beforeAll
was relying on the top-beforeEach
to have run before the block was entered, you’re going to be out of luck.
This behaviour compounds with yet another level of nesting:
top level before all
top level before each
top level test 1
top level before each
top level test 2nested before all
top level before each
nested before each
nested test 1
top level before each
nested before each
nested test 2
// so many beforeEach calls!
inner-nested before all
top level before each
nested before each
inner-nested before each
inner-nested test 1top level before each
nested before each
inner-nested before each
inner-nested test 2
I don’t think the way the beforeEach
handles test vs describe blocks differently is immediately obvious and something worth knowing about. I should also mention that afterEach
also runs this way, although the order is inverted.
Do you have some beforeEach
blocks running more often than you realised?