Skip to main content
100%

Idiomatic React Testing Patterns

✓ Published0🌍 Public
Aakilbekov
Last edited Jul 13, 2016
Created on Jul 13, 2016

This example demonstrates four idiomatic patterns for testing React components, organized by purity: basic rendering, stateless interactions, stateful interactions, and instance methods. It shows how to structure test setup with a `getComponent` helper that provides default props while allowing per-test overrides. The code uses Mocha, Chai, Sinon, React’s `TestUtils.renderIntoDocument`, `ReactDOM.render`, and `ReactDOM.findDOMNode` to render components and simulate user events, with re-rendering for stateful cases. The patterns cover asserting prop-driven output, callback invocation, state changes, and direct method calls.

AI-generated description

Idiomatic React Testing Patterns

Testing React components seems simple at first. Then you need to test something that isn't a pure interaction and things seem to break down. These 4 patterns should help you write readable, flexible tests for the type of component you are testing.

Setup

I recommend doing all setup in the most functional way possible. If you can avoid it, don't set variables in a beforeEach. This will help ensure tests are isolated and make things a bit easier to reason about. I use a pattern that gives great defaults for each test example but allows every example to override props when needed:

const getComponent = (props = {}) => {
	// Any test can override the default props by passing an object to the getComponent function
	props = Object.assign({
		onChange: sinon.spy(),
		title: 'Test Title',
		color: 'red'
	}, props);

	const component = ReactDOM.findDOMNode(TestUtils.renderIntoDocument(
		<MyComponent {...props} />
	));

	return Object.assign(props, { component });
};

// Usage
const { component, onChange } = getComponent();
const { component } = getComponent({ onChange: someFunc });

The Patterns

There are 4 primary patterns that I've identified, have more ideas? Provide examples and rationale in the comments!

Preferred "pure" patterns

Impure patterns

Inevitably you will have impure components, these patterns provide consistency in how you test these types of interactions

  • Stateful interactions: how interactions change render results relying on this.state or how lifecycle hooks behave
  • Instance methods: how the component interacts with external libraries or APIs (very rare)

Disclaimer

You may have a different testing stack and YMMV with how well these patterns work within that environment. For reference, here is the stack we use at Cratejoy and the one I've had the most success with:

  • Karma test runner (configured with browserify + babel)
  • Mocha test framework
  • Chai expect library
  • Sinon mock library

Similar vizzes