jest: Jest React Native - Invariant Violation: Native module cannot be null.

Do you want to request a feature or report a bug? bug

What is the current behavior? When I run ‘npm run jest’, I got an error like this. Invariant Violation: Native module cannot be null.

  at invariant (node_modules/fbjs/lib/invariant.js:38:15)
  at Linking.NativeEventEmitter (node_modules/react-native/Libraries/EventEmitter/NativeEventEmitter.js:32:1)
  at new Linking (node_modules/react-native/Libraries/Linking/Linking.js:119:141)
  at Object.<anonymous> (node_modules/react-native/Libraries/Linking/Linking.js:191:16)
  at Object.get Linking [as Linking] (node_modules/react-native/Libraries/react-native/react-native.js:91:22)
  at Object.<anonymous> (node_modules/react-native-experimental-navigation/NavigationRootContainer.js:15:36)

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal repository on GitHub that we can npm install and npm test.

  1. cd react-native-router-flux
  2. npm install
  3. cd Example
  4. npm install
  5. npm run jest

https://github.com/MechanicKim/react-native-router-flux

What is the expected behavior? Pass the jest test and update snapshot

Run Jest again with --debug and provide the full configuration it prints. Please mention your node and npm version and operating system. Darwin 16.1.0 node v7.2.0 npm v3.10.9

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 11
  • Comments: 27 (4 by maintainers)

Commits related to this issue

Most upvoted comments

Figured it out

Created a file jest/setup.js with the following content

jest.mock('Linking', () => {
  return {
    addEventListener: jest.fn(),
    removeEventListener: jest.fn(),
    openURL: jest.fn(),
    canOpenURL: jest.fn(),
    getInitialURL: jest.fn(),
  }
})

Add changed my package.json

...
"jest": {
	"preset": "react-native",
	"setupFiles": ["jest/setup.js"]
},
...

Although there has been some change behaviour because previously this mock was not required.

Set the preset to “react-native” and remove jest-react-native. It isn’t needed any more with 0.38!

Cleaner solution using __mocks__ Create __mocks__ directory next to __tests__ and place react-native.js with

const rn = require('react-native')
jest.mock('Linking', () => {
  return {
    addEventListener: jest.fn(),
    removeEventListener: jest.fn(),
    openURL: jest.fn(),
    canOpenURL: jest.fn(),
    getInitialURL: jest.fn(),
  }
})
module.exports = rn

the same thing happened to me, had to

jest.mock('PushNotificationIOS', () => ({
  addEventListener: jest.fn(),
  requestPermissions: jest.fn(),
}));

Hmmm, I’ve had to amend these slightly. I’m using react-native-push-notification version 2.2.1.

jest.mock('PushNotificationIOS', () => {
  return {
    addEventListener: jest.fn(),
    requestPermissions: jest.fn(() => Promise.resolve()),
    getInitialNotification: jest.fn(() => Promise.resolve()),
  }
});

Because requestPermissions and getInitialNotification seem to return a promise now. Would love this to be stable.

I am also getting this error.

Steps to reproduce:

  • react-native init a fresh project with 0.39
  • run jest, tests pass
  • Add dependency “react-native-router-flux”: “^3.37.0”
  • Add import import { Router, Scene } from ‘react-native-router-flux’
  • run jest, get the above error

The current jest setup.js does not mock out Linking.

I was able to get past the error by adding

Linking: {
  addEventListener: jest.fn(),
  removeEventListener: jest.fn(),
  openURL: jest.fn(),
  canOpenURL: jest.fn(),
  getInitialURL: jest.fn(),
},

After AsyncLocalStorage {...},

The problematic line is const Linking = require('react-native').Linking; from the react-native-experimental-navigation fork that react-native-router-flux uses.

package.json:

{
	"name": "test",
	"version": "0.0.1",
	"private": true,
	"scripts": {
		"start": "node node_modules/react-native/local-cli/cli.js start",
		"test": "jest"
	},
	"dependencies": {
		"react": "15.4.1",
		"react-native": "^0.39.0",
		"react-native-router-flux": "^3.37.0"
	},
	"jest": {
		"preset": "react-native"
	},
	"devDependencies": {
		"babel-jest": "17.0.2",
		"babel-preset-react-native": "1.9.0",
		"jest": "17.0.3",
		"react-test-renderer": "15.4.1"
	}
}

@cpojer Is there any way to mock out react native Linking globally without duplicating the setup.js file?

@kyangy I think in the end I didn’t need to. The library that was causing problems was react-native-push-notification, which I mocked as follows:

jest.mock('react-native-push-notification', () => {
    return {
        addEventListener: jest.fn(),
        removeEventListener: jest.fn(),
        requestPermissions: jest.fn(),
        configure: jest.fn()
    }
});

Have you tried creating a jest/__mocks__/pusher.js file that looks something like:

module.exports = {
    // whatever methods or properties are being accessed via the pusher object
}

I was able to narrow down exactly what libraries and methods needed to be mocked by systematically removing all imports from the component/file under test, and commenting out a lot of code, and reintroducing things one at a time. I mocked whatever caused the test to squawk.

In Jest 18.1, doing ./jest-setup.js will be resolved from the location of package.json.

We merged this preset back into react-native; please send mocks and PRs directly there.

I’ve got this problem as well on RN 38 with Jest 17.0.3. The problem is coming from NetInfo and react-native-router-flux. This is how i Implemented this from your solution :

jest.mock('Linking', () => {
  return {
    addEventListener: jest.fn(),
    removeEventListener: jest.fn(),
    openURL: jest.fn(),
    canOpenURL: jest.fn(),
    getInitialURL: jest.fn(),
  }
});

jest.mock('NetInfo', () => {
  return {
    isConnected: {
      fetch: () => {
        return new Promise((accept, resolve) => {
          accept(true);
        })
      }
    }
  }
});

@JeroenNelen I’ve managed to workaround this with prepending <rootDir>:

"jest": {
    "preset": "jest-react-native",
    "setupFiles": [
      "<rootDir>/jest-setup.js"
    ]
  }```

Ugly, but works.
jest.mock('react-native-gps-state', () => {
  return {
    nativeMethodToMock: jest.fn(),
    anotherNativeMethod: jest.fn()
  }
})

Edited; I had to refer to the file via “./jest/setup.js” since updating, before the “jest/setup.js” was working without any issues (I found the solution here: https://github.com/facebook/react-native/issues/11585)


Any update on this? I was using this workaround: "jest": { "preset": "react-native", "setupFiles": [ "jest/setup.js" ], "collectCoverage": true, "verbose": true },

But since updating all my packages to the latest versions today, Jest keeps giving this error: Error: Jest: Module "jest/setup.js" in the "setupFiles" option was not found.

Any clue why it can no longer find the file? It hasn’t moved or anything.

Kind regards,

I have a similar issue. I have a saga that is importing:

import Camera from 'react-native-camera';

This throws the error:

 FAIL  js/sagas/App/__tests__/watchCheckDevicePermissions-test.js
  ● Test suite failed to run

    TypeError: Cannot read property 'Aspect' of undefined

      at Object.<anonymous> (node_modules/react-native-camera/index.js:254:78)
      at Object.<anonymous> (js/sagas/App/watchCheckDevicePermissions.js:26:95)
      at Object.<anonymous> (js/sagas/App/__tests__/watchCheckDevicePermissions-test.js:2:34)

I tried to define a Camera mock in ./js/jest/setup.js:

jest.mock('Camera', () => {
    return {
        Aspect: {}
    }
});

Which is required in package.json setupFiles. All my tests start throwing the error:

Cannot find module 'Camera' from 'setup.js'

I also get the Invariant error for other libraries. For example, Pusher. I get the Cannot find module warning if I try to mock Pusher:

jest.mock('Pusher', () => {
    return {
        addEventListener: jest.fn(),
        removeEventListener: jest.fn()
    }
});

This is my jest config in package.json:

  "jest": {
    "preset": "react-native",
    "setupFiles": ["./js/jest/setup.js"],
    "transformIgnorePatterns": [
      "node_modules/(?!react-native||@shoutem)"
    ]
  },

React version: 15.4.2 React-native version: ^0.40.0 Jest version: ^19.0.0

I think it’s more the job of the react-native preset to figure it out, rather than jest itself