Jest’s ‘beforeEach’ may not be running the way you think it does…

Joshua Toth
3 min readMar 17, 2021

--

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 2
nested 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 1
top 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?

--

--