speedskater/babel-plugin-rewire

Jest test on function that's not exported

Opened this issue ยท 18 comments

I'm trying to do unit tests using Jest on a function that is not exported. I'm unable to use Rewire because I'm in a React Native environment with babel. I only want to get the function but I can't figure this out from the documentation. For example, let's say I have a file file.js that has a function foo. How do I reference this function from my test file.

file.js:

function foo() {
  ...
}

file.tests.js:

// how do I __get__ foo?

Thanks!

in file.spec.js you should be able to do

import file from './file';

const foo = file.__get__('foo');
const returnValueOfFoo = foo(params)

I'm currently not able to get past the import presumably due to improper configuration. Currently I have Jest configured to work with Babel in my setup. Then, I've configured Babel to work with this plugin via .babel.rc like this:

{
  "presets": ["react-native"],
  "plugins": [
    "transform-object-rest-spread",
    "rewire"
  ]
}

However, I'm getting the following error when I npm test, generated by the import line:

node_modules/react-native/jest/setup.js: babel-plugin-jest-hoist: The module factory of `jest.mock()` is not allowed to reference any out-of-scope variables.
    Invalid variable access: _get__
    Whitelisted objects: Array, ArrayBuffer, Boolean, DataView, Date, Error, EvalError, Float32Array, Float64Array, Function, Generator, GeneratorFunction, Infinity, Int16Array, Int32Array, Int8Array, InternalError, Intl, JSON, Map, Math, NaN, Number, Object, Promise, Proxy, RangeError, ReferenceError, Reflect, RegExp, Set, String, Symbol, SyntaxError, TypeError, URIError, Uint16Array, Uint32Array, Uint8Array, Uint8ClampedArray, WeakMap, WeakSet, arguments, expect, jest, require, undefined, DTRACE_NET_SERVER_CONNECTION, DTRACE_NET_STREAM_END, DTRACE_HTTP_SERVER_REQUEST, DTRACE_HTTP_SERVER_RESPONSE, DTRACE_HTTP_CLIENT_REQUEST, DTRACE_HTTP_CLIENT_RESPONSE, global, process, Buffer, clearImmediate, clearInterval, clearTimeout, setImmediate, setInterval, setTimeout, console, 0.706316033888597, __core-js_shared__.
    Note: This is a precaution to guard against uninitialized mock variables. If it is ensured that the mock is required lazily, variable names prefixed with `mock` are permitted.

      at invariant (node_modules/babel-plugin-jest-hoist/build/index.js:13:11)

Note:

  • This has nothing to do with the __get__ line in your example; jest never gets that far.
  • It's complaining about _get__ with a single underscore before 'get'; weird.

@ryanhomer try:

{
  "presets": [
    "es2015",
    "stage-0"
  ],
  "env": {
    "test": {
      "plugins": [
        "istanbul",
        "babel-plugin-rewire"
      ]
    }
  }
}

Looks like stage-0 is no longer a built-in option so I had to npm install babel-preset-stage-0 --save-dev then add babel-preset-stage-0 to presets instead.

It took about 3 seconds longer than before to throw the error but I'm still getting the same error. Any further suggestions are appreciated.

Thanks.

@ryanhomer did you add istanbul and switch your rewire to babel-install-rewire?

Yes, I copied/pasted the "env" section exactly as is. For the "presets" section, I tried several combinations of react-native, es2015 and babel-preset-stage-0.

@ryanhomer oh it looks like it doesn't like your use of babel-plugin-jest-hoist, try uninstalling that and removing references from it.

@ryanhomer @Tmassery This was happening to me too, also on a React Native project. I didn't want to track down the source of babel-plugin-jest-hoist because it's not something I installed directly - it's a dependency of another package.

But, looking at https://github.com/varmais/react-native-unit-tests/blob/master/.babelrc#L6, I decided to add

  "env": {
    "mocha": {
      "plugins": [
        "rewire"
      ]
    }
  }

to my babelrc and it worked!

Oops nevermind, that was crazy talk. I can only get it to work by editing my local version of babel-plugin-jest-hoist ๐Ÿ˜ข

Is it incompatible with jest-hoist? I get a Invalid variable access: _extends whenever I use rewire babel plugin.

I'm having the same issue like @ryanhomer.
I'm working on a react-native app and I'm writing my unit-tests with jest.

When adding babel-plugin-rewire to my .babelrc-file I'm always getting the following issue:

Test suite failed to run

***/node_modules/react-native/jest/setup.js: babel-plugin-jest-hoist: The module factory of `jest.mock()` is not allowed to reference any out-of-scope variables.
    Invalid variable access: _get__

Issue is still happening :(

same error in react native project.

app/node_modules/react-native/jest/setup.js: babel-plugin-jest-hoist: The module factory of jest.mock() is not allowed to reference any out-of-scope variables.
Invalid variable access: get_

jvivs commented

Try out this solution: #109 (comment).

I was able to get past the invalid variable access issue by switching from import * syntax to explicit imports.

Explicit imports seem like a better idea to me anyways :)

If anyone else is still having this problem: I incorporated @sarahatwork's local edit into an npm pretest:

"pretest": "sed -e 's/:__/:_/' -i node_modules/babel-plugin-jest-hoist/build/index.js"

That way it still works even if babel-plugin-jest-hoist gets reinstalled. Even with that, I also needed to follow some of the advice in the solution referenced by @jvivs and make sure there was a reference in my module to anything in it I wanted to test.

same error here with react native.

@ryanhomer I was able to reproduce your error about _get__ with a single underscore before 'get';
The error occurs when you define a module and you try to test a function that is not exported and it is not used by a function that is exported.

This example should work:

file.js:

export default function bar() {
 ...
 foo();
 ...
}

function foo() {
  ...
}

file.tests.js:

const foo = require("./file").__get__("foo"); // it works

Is there any solution to how can we mock Function without exporting and passing the test data for that to complete our test code? Also, can you guys help me how to pass data to the useState for the test code?