React-native-firebase: [v6][jest +@ react-native-firebase/app] Native Module Can not be null

Created on 11 Aug 2019  ·  15Comments  ·  Source: invertase/react-native-firebase


Issue



Describe your issue here

I am trying to use jest + enzyme to test a component using firebase auth.
The result is below:
Screen Shot 2019-08-10 at 11 10 18 PM


Project Files






iOS

Click To Expand

#### `ios/Podfile`: - [ ] I'm not using Pods - [x] I'm using Pods and my Podfile looks like:

pod 'React', :path => '../node_modules/react-native/'
  pod 'React-Core', :path => '../node_modules/react-native/React'
  pod 'React-DevSupport', :path => '../node_modules/react-native/React'
  pod 'React-fishhook', :path => '../node_modules/react-native/Libraries/fishhook'
  pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS'
  pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation'
  pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob'
  pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image'
  pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS'
  pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network'
  pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings'
  pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text'
  pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration'
  pod 'React-RCTWebSocket', :path => '../node_modules/react-native/Libraries/WebSocket'

  pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact'
  pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi'
  pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor'
  pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector'
  pod 'yoga', :path => '../node_modules/react-native/ReactCommon/yoga'

  pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
  pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
  pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'

  pod 'RNFBAuth', :path => '../node_modules/@react-native-firebase/auth/ios'
#### `AppDelegate.m`:
// N/A


Android

Click To Expand

#### Have you converted to AndroidX? - [ ] my application is an AndroidX application? - [ ] I am using `android/gradle.settings` `jetifier=true` for Android compatibility? - [ ] I am using the NPM package `jetifier` for react-native compatibility? #### `android/build.gradle`:

// N/A
#### `android/app/build.gradle`:
// N/A
#### `android/settings.gradle`:
// N/A
#### `MainApplication.java`:
// N/A
#### `AndroidManifest.xml`:
<!-- N/A -->


Environment

Click To Expand

**`react-native info` output:**

info Fetching system and libraries information...
System:
    OS: macOS 10.14.5
    CPU: (12) x64 Intel(R) Core(TM) i9-8950HK CPU @ 2.90GHz
    Memory: 5.26 GB / 32.00 GB
    Shell: 3.0.2 - /usr/local/bin/fish
  Binaries:
    Node: 12.6.0 - /usr/local/bin/node
    Yarn: 1.16.0 - /usr/local/bin/yarn
    npm: 6.9.0 - /usr/local/bin/npm
    Watchman: 4.9.0 - /usr/local/bin/watchman
  SDKs:
    iOS SDK:
      Platforms: iOS 12.4, macOS 10.14, tvOS 12.4, watchOS 5.3
    Android SDK:
      API Levels: 27, 28
      Build Tools: 28.0.3, 29.0.0
      System Images: android-28 | Google Play Intel x86 Atom
  IDEs:
    Android Studio: 3.2 AI-181.5540.7.32.5056338
    Xcode: 10.3/10G8 - /usr/bin/xcodebuild
  npmPackages:
    react: 16.8.6 => 16.8.6
    react-native: 0.60.4 => 0.60.4
  npmGlobalPackages:
    react-native-cli: 2.0.1
- **Platform that you're experiencing the issue on**: - [ ] iOS - [ ] Android - [ ] **iOS** but have not tested behavior on Android - [ ] **Android** but have not tested behavior on iOS - [x] Both - **`react-native-firebase` version you're using that has this issue:** - `@react-native-firebase/app 0.1.2` - **`Firebase` module(s) you're using that has the issue:** - `@react-native-firebase/auth 0.1.2` - **Are you using `TypeScript`?** - `N`




Think react-native-firebase is great? Please consider supporting all of the project maintainers and contributors by donating via our Open Collective where all contributors can submit expenses. [Learn More]

Stale

Most helpful comment

@SiM07 solution didn't work for me, as I was still getting analytics_1.default is not a function

This is what did it for me:

jest.mock('@react-native-firebase/analytics', () => {
  return () => ({
    logEvent: jest.fn(),
    setUserProperties: jest.fn(),
    setUserId: jest.fn(),
    setCurrentScreen: jest.fn(),
  })
});

Hope it is useful for others!

All 15 comments

So, jest and enzyme aren't running on an emulator right? How would native code work?

I mock out native stuff for jest

So, jest and enzyme aren't running on an emulator right? How would native code work?

I mock out native stuff for jest

So the problem here is that I should mock the native module. But I don't know how I should mock it. Should I mock the '@react-native-firebase/app'? If yes, can you give me a direction of how should I mock it?

not sure on v6, I'm still working on v5 until notifications is done on v6

for v5 I use a setup file from setupFilesAfterEnv array in jest.config.js that looks like this:

more __mocks__/mockFirebase.ts

/* eslint-disable no-undef */
jest.mock('react-native-firebase', () => ({
  messaging: jest.fn(() => ({
    hasPermission: jest.fn(() => Promise.resolve(true)),
    subscribeToTopic: jest.fn(),
    unsubscribeFromTopic: jest.fn(),
    requestPermission: jest.fn(() => Promise.resolve(true)),
    getToken: jest.fn(() => Promise.resolve('myMockToken')),
  })),
  notifications: jest.fn(() => ({
    onNotification: jest.fn(),
    onNotificationDisplayed: jest.fn(),
  })),
  analytics: jest.fn(() => ({
    logEvent: jest.fn(),
    setUserProperties: jest.fn(),
    setUserId: jest.fn(),
    setCurrentScreen: jest.fn(),
  })),
}));

I haven't mocked auth, but it should be sort of like that, you'd specify the module, and inside of it mock things out?

@mikehardy

Thanks for the info. It is really helpful. Do you know where I can get help for the v6?

for mocking, I do not - but it should be the same style

Hello 👋, to help manage issues we automatically close stale issues.
This issue has been automatically marked as stale because it has not had activity for quite some time. Has this issue been fixed, or does it still require the community's attention?

This issue will be closed in 15 days if no further activity occurs.
Thank you for your contributions.

Closing this issue after a prolonged period of inactivity. If this is still present in the latest release, please feel free to create a new issue with up-to-date information.

I use :

import analytics from "@react-native-firebase/analytics";

analytics().logEvent("add_to_cart", params);

And in mockFirebase.js

jest.mock('@react-native-firebase/analytics', () => {
  analytics: jest.fn(() => ({
    logEvent: jest.fn(),
    setUserProperties: jest.fn(),
    setUserId: jest.fn(),
    setCurrentScreen: jest.fn(),
  }))
});

@SiM07 solution didn't work for me, as I was still getting analytics_1.default is not a function

This is what did it for me:

jest.mock('@react-native-firebase/analytics', () => {
  return () => ({
    logEvent: jest.fn(),
    setUserProperties: jest.fn(),
    setUserId: jest.fn(),
    setCurrentScreen: jest.fn(),
  })
});

Hope it is useful for others!

I had to add this line into one of my setupFiles in jest. I couldn't get rid of Native Module cannot be null message without it.

import { NativeModules } from 'react-native'
....
NativeModules.RNFBAppModule = {}

and after that since v6 all modules are separate, you have to mock all functions for each module separately.

jest.mock('@react-native-firebase/analytics', () => {
  return () => ({
    logEvent: jest.fn(),
    setUserProperties: jest.fn(),
    setUserId: jest.fn(),
    setCurrentScreen: jest.fn()
  })
})

jest.mock('@react-native-firebase/crashlytics', () => {
  return () => ({
    recordError: jest.fn()
  })
})

// USE BELOW TEMPLATE TO MOCK OTHER MODULES
jest.mock('@react-native-firebase/ADD_OTHER_MODULES_YOU_USE', () => {
  return () => ({
    MOCK_EACH_FUNCTION: jest.fn()
  })
})

In my project with "@react-native-firebase/analytics": "^6.1.0" and "jest": "^24.8.0" I mock Analytics in __mocks__/@react-native-firebase/analytics.js.

export default {
    analytics: jest.fn(() => ({
        setUserId: jest.fn(),
        setUserProperties: jest.fn(),
        setCurrentScreen: jest.fn(),
        logEvent: jest.fn(),
    }))
};

There is no need of any extra configuration. https://jestjs.io/docs/en/manual-mocks#mocking-node-modules

I hope that help!

Im still facing the issue
Have in my package.json

    "@react-native-firebase/app": "^6.7.1",
    "@react-native-firebase/crashlytics": "^6.7.1",
    "@react-native-firebase/database": "^6.7.1",
    "@react-native-firebase/messaging": "^6.7.1",

in my setup-jest.js

jest.mock('@react-native-firebase/app');

jest.mock('react-native-notifications');

jest.mock('@react-native-firebase/database');

jest.mock('@react-native-firebase/crashlytics', () => () => ({
  recordError: jest.fn(),
  logEvent: jest.fn(),
  setUserProperties: jest.fn(),
  setUserId: jest.fn(),
  setCurrentScreen: jest.fn(),
}));


jest.mock('@react-native-firebase/messaging', () => () => ({
  hasPermission: jest.fn(() => Promise.resolve(true)),
  subscribeToTopic: jest.fn(),
  unsubscribeFromTopic: jest.fn(),
  requestPermission: jest.fn(() => Promise.resolve(true)),
  getToken: jest.fn(() => Promise.resolve('myMockToken')),
  onTokenRefresh: jest.fn((callback) => callback(Promise.resolve('Example'))),
}));

But im still getting

  ● Test suite failed to run

    Invariant Violation: Native module cannot be null.

      at invariant (node_modules/invariant/invariant.js:40:15)
      at RNFBNativeEventEmitter.invariant (node_modules/react-native/Libraries/EventEmitter/NativeEventEmitter.js:36:7)
      at new RNFBNativeEventEmitter (node_modules/@react-native-firebase/app/lib/internal/RNFBNativeEventEmitter.js:24:5)
      at Object.<anonymous> (node_modules/@react-native-firebase/app/lib/internal/RNFBNativeEventEmitter.js:48:16)
      at Object.<anonymous> (node_modules/@react-native-firebase/app/lib/internal/registry/nativeModule.js:21:1)

Idk what more mock

Also facing the same issue as @ccanalesb -- any guidance on how to mock @react-native-firebase/app on v6 would be appreciated!

I have this file listed as a setup file in jest config

cat __mocks__/reactNativeFirebase.ts:

/* eslint-disable no-undef */
jest.mock('@react-native-firebase/app', () => ({
  messaging: jest.fn(() => ({
    hasPermission: jest.fn(() => Promise.resolve(true)),
    subscribeToTopic: jest.fn(),
    unsubscribeFromTopic: jest.fn(),
    requestPermission: jest.fn(() => Promise.resolve(true)),
    getToken: jest.fn(() => Promise.resolve('myMockToken')),
  })),
  notifications: jest.fn(() => ({
    onNotification: jest.fn(),
    onNotificationDisplayed: jest.fn(),
  })),
  analytics: jest.fn(() => ({
    logEvent: jest.fn(),
    setUserProperties: jest.fn(),
    setUserId: jest.fn(),
    setCurrentScreen: jest.fn(),
  })),
}));

// web mock
jest.mock('firebase/app', () => ({
  analytics: jest.fn(() => ({
    logEvent: jest.fn(),
  })),
}));

Mocking the Native Event Emitter unlocked the situation for me:

// ... other mocks before

jest.mock("react-native/Libraries/EventEmitter/NativeEventEmitter");
Was this page helpful?
0 / 5 - 0 ratings