How to run Jest tests with Rewire plugin

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