Skip to content

React Testing Library unittest

Jean-Michel FRANCOIS edited this page May 3, 2023 · 3 revisions

Context

We Have to migrate from enzyme to RTL because React 18 has a internal breaking change that makes enzyme dead by design. React now schedule render. So we have to rewrite a bunch of tests suite (360).

But RTL came with a real difference: no access to react component, no access to state. It looks like a more end to end approach. As we still need unittest we have to find tricks to tests only one component and not the entire subset.

Also RTL is based on jsdom so there is limitations, we will try to list them.

Snapshot

Snapshot are nice to keep a trace of the render. Just do one per component seems enough. This is usefull to see impact when a DOM is changed for example after upgrading a library to see if the dom has changed.

Avoid doing 10 snapshots has they do not fit any tests except it('should render', () => {

mock dependencies

As component is about responsabilities it is ok to mock underlying components or dependencies. This is not considered as a code smell ref

The goal of mock can be:

  • make it easier to test the component
  • gather information of state of the current component you test

First tips is to use dataset.props:

jest.mock('../../pickers/CalendarPicker', () => {
	return props => <div data-testid="CalendarPicker" data-props={JSON.stringify(props)} />;
});
// ..tests
		// then
		const props = JSON.parse(screen.getByTestId('CalendarPicker').dataset.props);
		expect(props).toMatchObject({
			manageFocus: true,
			other: 'custom props',
			selectedDate: '2007-01-01T23:00:00.000Z',
			useUTC: false,
		});

The drawback is you don't have access to function but this is often OK as function are most of the time event handler. You can add buttons to manage event handler out of the scope of your current component. But this is usefull only if the current component create this handler. if it is only a pass through it doesn't make sens to unittest it.

jest.mock('../../views/DateTimeView', () =>
	jest.fn(props => (
		<div data-testid="DateTimeView" data-props={JSON.stringify(props)}>
			<button onClick={() => props.onTitleClick()}>Select MonthYearView</button>
		</div>
	)),
);