DEV Community

Yuri Toledo
Yuri Toledo

Posted on

Enzyme or react-testing-library and why?

Top comments (15)

Collapse
 
lacasa profile image
π™»πšŠπšŒπšŠπšœπšŠ

I've been using Enzyme for a couple of years, and I've been happy with most of the time. But it happened to me a couple of times that I misread a snapshot, and a bug ended up in production!

Also, I've been teaching React to some colleagues lately, and I've realized it is not easy to understand Enzyme.

Add to this facts that I like to learn new stuff and use it in project always, and you'll understand why I switched recently to react-testing-library.

It is a different way of doing tests, tbh. People tend to understand it earlier because it is more similar to other unit tests techniques.

The only tradeoff (if you can call that) is that I have to mock way more stuff using react-testing-library than using Enzyme. It makes tests more verbose, but... I think I like it better! It helps me isolate what to test from a component.

So, that's my experience so far. Hope you find it useful.

Collapse
 
yuritoledo profile image
Yuri Toledo

I'm learning RTL and I use enzyme. I Try to reproduce the same tests that I use on enzyme to RTL, but I cant.

For example, how could I check if all form fields was filled and compare with a object that I'll send to backend?

Collapse
 
lacasa profile image
π™»πšŠπšŒπšŠπšœπšŠ

From my experience, you'll have to rethink how to test stuff most of the time. A direct conversion from Enzyme to RTL won't work.

I always try to avoid testing implementation details. I don't have much details about your example, but in RTL is quite easy to get/set fields content, then you have to find the submit button, fire the click event, and expect some data to be sent.

I found way more difficult to test render props for instance...

Thread Thread
 
yuritoledo profile image
Yuri Toledo

hmmm I see.

And its hard to find material to study, I cant understand the Kodds examples too much :/
And I hate the fact that I cant find a comp by id or name hehe

Thread Thread
 
lacasa profile image
π™»πšŠπšŒπšŠπšœπšŠ

You'll find the way, no worries...

I ended up using tons of data-testid in the mocks (I try really hard to avoid them in the real code).

Thread Thread
 
yuritoledo profile image
Yuri Toledo

I wanna try to avoid using it too, but how I use 3rd party components, I can't use htmlFor for example, and I rarely use placeholder

Thread Thread
 
lacasa profile image

If you are using 3rd party components for inputs/labels, that's perfect! You don't need to test that whatever they do internally works, you just need to test that your component does what it needs, so you can mock them.

jest.mock('ui-library/Input', () =>
  jest.fn(({value, handleChange}) => <input data-testid="input" onChange={handleChange} value={value} />)
);

it('should do magic', () => {
  const {getByTestId} = render(<Component />);

  // we test that the component is rendering
  expect(getByTestId('input').value).toBeInTheDocument();

  // we test that the component shows the proper value
  expect(getByTestId('input').value).toEqual(oldValue);

  // we test that Component can handle change events
  // (we don't care how Input does that internally)
  fireEvent.change(getByTestId('input'), newValue);
  expect(getByTestId('input').value).toEqual(newValue);
});

The code might have errors, but the I think the idea is clear enough!

Thread Thread
 
yuritoledo profile image
Yuri Toledo

Yeah, its clear, thank you bro

Thread Thread
 
nersoh profile image
Nelson Henrique • Edited

"And I hate the fact that I cant find a comp by id or name hehe"

I don't know if you already figured out how to do it, but I actually can by doing, for example:

const { container } = render(Component);
expect(container.querySelector("#myid")).not.toBeNull();

Thread Thread
 
lacasa profile image

You can create your custom selectors like this:

import { queryByAttribute, render } from '@testing-library/react';

const getByName = queryByAttribute.bind(null, 'name');

it('should...', () => {
  const { container } = render(<Component />);
  expect(getByName(container, 'the-name').toEqual(...)
})

I have some custom selectors created in a utils file (name, type, id...).

Collapse
 
harkinj profile image
harkinj

The more u mock the less confidence u will have that all is well in the app/component.
I'd favor more integration type tests (that do less mocking , perhaps only mock out network/rest api cals) over 'unit' tests. As very unit versus integration is a thorny subject :)

Collapse
 
yuritoledo profile image
Yuri Toledo

have u any example ?

Collapse
 
harkinj profile image
harkinj

Favour Integration Tests - great article by the famous Kent C Dodds. His article says it better than me :)

Thread Thread
 
jdsandifer profile image
J.D. Sandifer

I think that article moved here: Write tests. Not too many. Mostly integration.

Collapse
 
srshifu profile image
Ildar Sharafeev

I used to use Enzyme for a long time in my projects. However, now it is on deprecation path and will not be compatible with future versions of React. Therefore, I decided to write a tool that will help me and my team to migrate our projects to RTL. Check my article: dev.to/srshifu/migrate-away-from-e...

It has links to the tool you can download and use in your project