JEST + React Testing Library: should I render my component with a beforeAll before tests?
Asked Answered
S

2

20

As the title says, I'm using RTL + Jest (with Create-react-app setup).

My question is if I should be using a beforeAll in each test pre-rendering the component within that block, so each test doesn't have to re-render the component from scratch since my test suites always start from the same base component. Is there a performance improvement by doing this?

For example, is there an improvement in doing this

describe("MyComponent", () => {
    beforeAll(() => {
        render(<MyComponent {...props} />);
    });

    it("tests something", () => {
        expect(something).toDoSomething();
    });

    it("tests something else", () => {
        expect(somethingElse).toDoSomethingElse();
    });
});

over this (other than being less verbose and re-writing the component rendering)?

describe("MyComponent", () => {

    it("tests something", () => {
        render(<MyComponent {...props} />);
        expect(something).toDoSomething();
    });

    it("tests something else", () => {
        render(<MyComponent {...props} />);
        expect(somethingElse).toDoSomethingElse();
    });
});

Should I be approaching my test suites differently by doing something else? Is it just a matter of personal preference?

I've read from Kent C Dodds blog this post where he mainly states it makes code less readable but doesn't talk about performance or if it has any kind of impact on the tests.

Splenius answered 16/5, 2020 at 12:44 Comment(0)
A
10

It is mostly a matter of personal preference, but also about how your component works. You may need to render your component in different contexts (props, mocked redux store, mocked provider...). Render component in beforeEach may be faster but makes it more difficult to change the test conditions.

In my experience, as a rule of thumb, presentational components are rendered in the test itself, because I want to test different sets of props to cover all cases. As they are dumb components (only props involved, few mocks, simple component logic), thoses tests are usually fast. This is "real unit testing" : testing a pure function I/O (I only write functional components in my current position).

For smart/bigger components, usually I test a group of components together (which is more an integration test), I have to setup mocks (redux, http services...), and tests tends to resemble to scenarios like you would see in Cypress, with user interactions. For those tests I render once in beforeEach, and write fewer but longer tests. I end up with a test execution time much longer, but with a high level of confidence (close to what E2E would give).

This is more or less what https://kentcdodds.com/blog/write-tests says (as I understand it), and so far it seems to be a solid approach.

Obvioulsy this is some general thoughts/personal insight, there is no one size fits all in this matter I think. The only goal is to gain confidence.

By the way, when choosing to rerender the component multiple times, don't forget to use the rerender function to prevent funny things to happen.

Aquarius answered 16/5, 2020 at 15:14 Comment(1)
This does not answer the OP's question. He's not interested in options that include renders with different mocked props. He clearly stated that his use-case was for the same render each time - "...my test suites always start from the same base component."Trituration
A
2

While It makes sense (to me) theoretically, at least with recent version of Jest and RTL, by default it won't work to render in beforeAll. You can get around Jest auto cleanup in afterEach, but the performance benefit is probably not much anyway.

Better approach may be to write longer / richer tests rather than falling into the old habit of treating RTL as a pure unit testing tool.

https://github.com/testing-library/react-testing-library/issues/541

Aquiline answered 12/4, 2022 at 16:3 Comment(1)
This advice saved me days. Longer / fuller / integration tests style high value tests. Thank youCorking

© 2022 - 2024 — McMap. All rights reserved.