petermakowski.io

Enzyme encourages bad testing practices

Enzyme encourages testing implementation details. This is bad practice and such tests can do more harm than good.

Typical enzyme test

it("displays a spinner on load", () => {
const wrapper = mount(<EditComponent />);
expect(wrapper.find("[data-testid='loading-details']").exists()
).toBe(true);
});

False positives

Tests that do not fail when you break the functionality are said to return a false positive. Arguably, the test above can never return a "true positive" as it's not even testing anything that's relevant for the end user. Even if the loading-details test id was added to the DOM, we'll never know for sure the expected loading indicator (like a spinner icon with a "loading" text) is returned by this component.

Even worse, it's possible that even the data-testid="loading-details" itself never appears in the DOM and this test still passes. This could happen if the underlying component doesn’t render the data-testid prop. Enzyme lets this test pass because it’s testing component instances instead of the output of these components - the DOM nodes.

False negatives

Refactoring should be encouraged and easy, with tests serving as an extra layer of confidence giving you immediate feedback if the application's functionality remained unchanged. This test can also break after doing some refactoring - giving you a false negative. All this test cares about is the test id which mean this test could fail even if the component still returns a loading spinner with a correct text (what's visible to the user).

Such tests do more harm than good

What's the point of writing tests in a way that doesn't give you confidence the application still works as expected?

All you're doing is giving yourself a false sense of security and creating more work whenever you need to make a change.