Testing for PropType Errors in React

Dave Ceddia bio photo By Dave Ceddia Comment

Testing PropType Errors

You might have a nice set of React tests, but are you checking for PropType errors? Wouldn’t it be nice to get failing tests whenever you forget to pass a required prop? Well, today is your lucky day.

You can test that no errors are printed to the console – this verifies that you didn’t forget any required props, among other things. You can use the Sinon library to do this, or your favorite spying library:

Check For Errors In One Test

// first:  npm install --save-dev sinon
import sinon from 'sinon';

// At the top of your tests:
beforeEach(() => {
  sinon.stub(console, 'error');
});

afterEach(() => {
  console.error.restore();
});

it('ensures no errors', () => {
  // ... do the test setup here ...

  // Make sure no errors were printed
  sinon.assert.notCalled(console.error);
});

DRY It Up

However, this code can get repetitive real fast. If you want to DRY it out, extract the code into a module like this:

// test-utils.js

import sinon from 'sinon';

export function stubConsoleError() {
  beforeEach(() => {
    sinon.stub(console, 'error');
  });

  afterEach(() => {
    console.error.restore();
  });
}

And then in your tests, import and call that function:

import { stubConsoleError } from './test-utils';

stubConsoleError();

it('ensures no errors', () => {
  // ... do the test setup here ...

  // Make sure no errors were printed
  sinon.assert.notCalled(console.error);
});

Never Allow Errors

And hey, maybe you want to go one step further and ensure that none of your tests print errors. You could move that assertion into the afterEach block like so:

// test-utils.js

import sinon from 'sinon';

export function noErrorsAllowed() {
  beforeEach(() => {
    sinon.stub(console, 'error');
  });

  afterEach(() => {
    sinon.assert.notCalled(console.error);
    console.error.restore();
  });
}

Then import it, call it, and you’re all set.

import { noErrorsAllowed } from './test-utils';

noErrorsAllowed();

it('works great', () => {
  // just write your test
  // the afterEach will check for errors
});

Check For Specific Errors

If you’d like to be a little more choosy about which errors you expect, you can check that console.error was called with specific text with a function like this:

function expectMissingProp(prop, component) {
  sinon.assert.calledWithMatch(console.error,
    new RegExp(`Required prop \`${prop}\` was not specified in \`${component}\``));
}

it('warns about missing props', () => {
  ReactDOM.render(<Person/>, div);

  // Require exactly 2 errors with specific text
  sinon.assert.callCount(console.error, 2);
  expectMissingProp('firstName', 'Person');
  expectMissingProp('lastName', 'Person');
});

Finito

There you go: now you can directly test for missing props in your unit tests.

comments powered by Disqus