minorgod
minorgod

Reputation: 692

Calling userEvent.setup() in beforeEach() - is it a good or bad pattern?

In a test suite that needs to call userEvent.setup() in multiple tests, sometimes I'll do the userEvent.setup() in a beforeEach and then just reference the same user var in multiple tests

let user: UserEvent
beforeEach(() => {
     user = userEvent.setup()
})

describe('SomeTests', () => {
    it('should test something', async () => {
        await user.click(someButton)
        ...
    })

    it('should test some other thing', async () => {
        await user.click(someButton)
        ...blahblahblah
    })
})

However, I'm concerned that this could cause issues with running tests in parallel, and it might be better to always do it like this:

describe('SomeTests', () => {
    it('should test something', async () => {
        const user = userEvent.setup()
        await user.click(someButton)
        ...blahblahblah
    })

    it('should test some other thing', async () => {
        const user = userEvent.setup()
        await user.click(someButton)
        ...blahblahblah
    })
})

Can anyone explain if doing it in beforeEach and sharing the user var between tests can cause problems and if it's better to get a fresh user instance in each individual test?

Sometimes Jest seems to have weird behavior when running tests in parallel and I'm just trying to eliminate all possible sources of the weirdness caused by having multiple references to the same objects interfering with each other between tests.

Upvotes: 8

Views: 1943

Answers (1)

Ken Gregory
Ken Gregory

Reputation: 7400

Prior to v14, setup was called for you when using the default export. The official docs for v14 recommend using the user-event methods from the instance returned by userEvent.setup():

You can also call the APIs directly on the default export. This will call setup internally and then use the method on the instance.

This exists to ease the transition to version 14 and writing simple tests. Using the methods on the instances returned by userEvent.setup() is recommended.

Also, the Writing tests with userEvent docs recommends calling this prior to rendering the element:

We discourage rendering or using any userEvent functions outside of the test itself - e.g. in a before/after hook - for reasons described in "Avoid Nesting When You're Testing".

The logic behind this is that it is way more valuable to have your tests be self-contained and understandable than it is to have clever abstractions that deduplicate testing logic.

I don't think there's any problem with using a beforeEach with respect to parallelization, because Jest runs describe and test blocks within a file serially. As long as your beforeEach is in the same file, it would be run before every test and should have the same effect as setup in each test, but now you need to declare a variable to store its results at a higher scope so it can be referenced in each test, which muddies the waters (as described in the article linked above).

Upvotes: 1

Related Questions