React Logo-full

Article covers React 0.12, a javascript library for building web-based user interfaces. Updated Jan 5, 2015 with an improved Rewire example.

Why is testing a React component so damn hard?

If your answer is “use Jest,” then see below, Why not Jest?.

Any given React component may include other components.

Example my-component.js, javascript + JSX:

var MyComponent = React.createClass({
  render: function() {
    return <div className="my-component">
     <SomeOtherComponent />

JSX transforms <SomeOtherComponent /> into a constructor call React.createElement(SomeOtherComponent) (more about React's vDOM.) This render-time generation of renderable elements makes mocking difficult.

What we need is someway to make SomeOtherComponent resolve to a factory for a mock component.

Modules to the Rescue

Testing components in isolation requires a module system, so that each test subject may be loaded in a clean state for each test.

Various javascript module APIs may be utilized during development: CommonJS, AMD, and the emergent ES6 Modules. To add more complexity to the choices, various build & bundling tools are available to consume modules: Require.js, Browserify, Webpack, and ES6 transpilers.

After liberal experimentation, this solution was found using CommonJS modules with Rewire to swap-out actual dependencies for mocks.

The recipe is:


Example my-component.js from above becomes modular:

var React = require("react");
var SomeOtherComponent = require("./some-other-component");

var MyComponent = React.createClass({
  render: function() {
   return <div className="my-component">
    <SomeOtherComponent />

module.exports = MyComponent;

With the dependency SomeOtherComponent declared as a variable in the top-level scope of the module, Rewire may be used to swap it out for a mock.

Example rewire-module.js, a Jasmine test helper to setup & teardown a rewired module:

var rewireModule = function rewireModule(rewiredModule, varValues) {
  var rewiredReverts = [];

  beforeEach(function() {
    var key, value, revert;
    for (key in varValues) {
      if (varValues.hasOwnProperty(key)) {
        value = varValues[key];
        revert = rewiredModule.__set__(key, value);

  afterEach(function() {
    rewiredReverts.forEach(function(revert) {

  return rewiredModule;

module.exports = rewireModule;

Example my-component-spec.js:

var React = require("react/addons");
var TestUtils = React.addons.TestUtils;
var rewire = require("rewire");
var rewireModule = require("./rewire-module");

describe('MyComponent', function() {
  var component;

  // `rewire` instead of `require`
  var MyComponent = rewire("./my-component");

  // Replace the required module with a stub component.
  rewireModule(MyComponent, {
    SomeOtherComponent: React.createClass({
      render: function() { return <div />; }

  // Render the component from the rewired module.
  beforeEach(function() {
    component = TestUtils.renderIntoDocument( <MyComponent /> );

  it("renders", function() {
    var foundComponent = TestUtils.findRenderedDOMComponentWithClass(
      component, 'my-component');


Why not Jest?

Facebook provides an official testing tool for React: Jest, which includes both a headless command-line test runner & a javascript testing API, based on Jasmine.

Jest as a test runner is yet-another contender amongst awesome multi-browser & headless Javascript test tools like Karma & Testem.

My own attempts to use Jest failed, because it:

  • Runs all specs against a virtual DOM (via JSDOM.) This prevents testing code that uses browser-native constructs like IndexedDB & Service Workers.
  • Offers no support for running tests in a browser, so all those fantastic visual dev & debugging tools provided by browsers are unavailable for tests.
  • Throws cryptic errors. This is a standard experience for javascript developers; doubly so, if the developer has used a Phantom.js test runner. The cryptic errors are made intolerable by the previous point: lack of options for in-browser debugging tools.

Happy Rewiring!

We burned days of time wrangling a React proof-of-concept into a neatly testable app and hope to save you frustration when developing with React.

Please tweet @marsi with any feedback.