How to run Jest tests with Rewire plugin

Another Jest connected post. How to test internal module functions that are not exported?

Problem

I want to test internal function defined inside ./index.js file without exporting it with module.exports. Let say that ./index.js looks similar to this (implementation details are irrelevant):

function someFunction(something) {
  return 'anything';
}

This function is not a part of public interface so exporting it just for testing with Jest seems like a bad idea/solution. Of course the following test won't work:

const someFunction = require('./index').__get__('someFunction');
describe('someFunction', () => {
  it('should work', () => {
    expect(someFunction()).toEqual('anything');
  });
});

The error message may looks as follows:

TypeError: require(...).__get__ is not a function

This is caused by lack of rewire package (as you may expect).

Solution

Use babel-plugin-rewire it's extremly easy to do. Just:

  1. Install it with yarn add --dev babel-plugin-rewire
  2. If you don't have babel-jest installed execute also yarn add --dev babel-jest
  3. Add plugin to the .babelrc config file:
{
  "plugins": ["babel-plugin-rewire"]
}

Now just run your tests as usual yarn jest. Everything should work smoothly. You don't have to install rewire itself.

If you are trying/willing to run Jest tests with Flow typed Javascript files check my other article Running Jest tests with Flow typed Javascript files.

Issues

The one which cost me a lot of time to figure it out.

TypeError: _get__(...) is not a function

According to the @joshnuss Github answer with babel-plugin-rewire you can't actually use __get__ method (or any other e.g. __Rewire__) for function/constant which is not referenced anywhere in your module file.

Example of a "buggy" module code which you won't be able to rewire and use __get__ method.

const test123 = () => {
  return true;
}

A "fixed" version (just reference test123 anywhere it doesn't have to be even executed):

const test123 = () => {
  return true;
}
test123;

And here is a test case which will fail if we use "buggy" implementation of the module.

const test123 = require('./index').__get__('test123');

test('test123', () => {
  expect(test123()).toEqual(true);
});

When such case might happen? Well, for example if you try to test some currently unused function (e.g. just a new internal module function).

Sources

https://www.npmjs.com/package/babel-plugin-rewire https://github.com/facebook/jest/issues/1003 https://www.npmjs.com/package/babel-plugin-rewire