speedskater / babel-plugin-rewire

A babel plugin adding the ability to rewire module dependencies. This enables to mock modules for testing purposes.
843 stars 90 forks source link

Jest test on function that's not exported #183

Open techrah opened 7 years ago

techrah commented 7 years ago

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!

Tmassery commented 7 years ago

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

import file from './file';

const foo = file.__get__('foo');
const returnValueOfFoo = foo(params)
techrah commented 7 years ago

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:

Tmassery commented 7 years ago

@ryanhomer try:

{
  "presets": [
    "es2015",
    "stage-0"
  ],
  "env": {
    "test": {
      "plugins": [
        "istanbul",
        "babel-plugin-rewire"
      ]
    }
  }
}
techrah commented 7 years ago

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.

Tmassery commented 7 years ago

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

techrah commented 7 years ago

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.

Tmassery commented 7 years ago

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

sarahatwork commented 7 years ago

~@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 😢

Apidcloud commented 7 years ago

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

ElinaSchaefer77 commented 6 years ago

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__
apolishch commented 6 years ago

Issue is still happening :(

ghost commented 6 years ago

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 6 years ago

Try out this solution: https://github.com/speedskater/babel-plugin-rewire/issues/109#issuecomment-200867686.

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 :)

jjd314 commented 6 years ago

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.

rsallar commented 4 years ago

same error here with react native.

apierr commented 4 years ago

@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

FSou1 commented 4 years ago

A solution for TypeScript is here: https://stackoverflow.com/questions/54697062/test-or-mock-a-not-exported-function-with-jest-using-typescript.

brijesh-imemori commented 6 months ago

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?