Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do unit testing in react native that uses firebase?

Im quite new to jest unit testing, so stuff like mocking modules is confusing.

In react native, there is a component that uses firebase databse that returns data from a given ref:

// when the data of the current user is available
userRef.child(user.uid).on('value', snap => {
  // check of val() consists data
  if (snap.val()) {
    let
      authUser = snap.val(),
      isPatient = authUser.type === "Patient",
      // We update the state object so that the component is re-rendered
      this.setState({
        // the ID of the current user
        authUserUID: user.uid,
        // the type of the current user (i.e. Doctor or Patient)
        authUserType: snap.val().type,
        // title of the dashboard based on the current user type
        activeTitle: snap.val().type === "Doctor" ? "My Patients" : "My Doctors",
      });
  }
});

I'm now trying to do unit testing which uses this component:

import 'react-native'
import React from 'react'
import renderer from 'react-test-renderer'
import LaunchScreen from "../../App/Containers/LaunchScreen";

test('LaunchScreen', () => {
  const tree = renderer.create( <LaunchScreen / > ).toJSON()
  expect(tree).toMatchSnapshot()
})

But it gives a weird error

RNFirebase core module was not found natively on iOS, ensure you have correctly included the RNFirebase pod in your projects Podfile and have run pod install

I have no idea since the firebase does return data if I run it. So why is it saying that RNFirebase cannot be found?

Thanks

Update

One of the answers have given a nice step by step instructions, and although it solves partially the proposed question; the error still persists. For example; I'm now getting this new error:

console.error node_modules\react-test-renderer\cjs\react-test-renderer.development.js:5530 The above error occurred in the component: in LaunchScreen

Consider adding an error boundary to your tree to customize error handling behavior.

TypeError: _reactNativeFirebase2.default.app is not a function

like image 885
Doe Avatar asked Apr 06 '18 21:04

Doe


People also ask

Can I use Firebase with React Native?

To get started, you must first setup a Firebase project and install the "app" module. React Native Firebase is the officially recommended collection of packages that brings React Native support for all Firebase services on both Android and iOS apps.

How do I connect React Native app with Firebase database?

Now we just need to initialize a Firebase app using the configuration details we got from Firebase. Once that is done, we will get a reference to the database service provided by Firebase for our app and export it: const app = initializeApp(firebaseConfig); const db = getDatabase(app); export { db };

How do I use Firebase in React Native command line?

In this step, we will add Firebase to our React Native app. For this, select Add Firebase to your Web App. In this Step, we will Register our web app to firebase so we will enter our App nickname and click on the register button. Copy your Firebase Config from Firebase dashboard and paste in into our app code.


1 Answers

https://gist.github.com/himanshusinghs/bd86262ce3c9e6f4d691b5242de707ef

Above is the link to a gist containing the mock of React Native Firebase. Implementation instructions are also there. I am summarising them here as well -

1. You will be mocking a node_module and to do so there are multiple ways depending upon your use case. But since you will need to mock Firebase for almost every component that utilizes it, we will be implementing a global mock of React Native Firebase module.

2. Create a __mocks__ folder in your project's root directory adjacent to your node_modules folder.

3. Now create a file named react-native-firebase.js inside the __mocks__ directory.

4. Copy paste the contents from RNFirebaseMock.js in the above gist to your react-native-firebase.js file.

How this works ?

Jest has an auto mocking feature. Now every time you will run your test cases using Jest, and whenever any of your test case will require react-native-firebase module, Jest will first look into __mocks__ folder and see if there is a react-native-firebase.js containing some mock implementation of the required module.

If there is then jest will require that mock implementation instead of original module otherwise it will continue on to require original react-native-firebase module.

Things to be noted

You need to observe that the name of the mock file that we created react-native-firebase.js inside __mocks__ folder is similar to the name of installation folder of actual react-native-firebase module. Just go to node_modules and scroll down till you find react-native-firebase folder.

Yes, the name of your mock implementation of a module need to be exactly same as the name of the module itself.

Things to do this point onwards

Congratulations for you started with unit testing and chose an awesome framework for the same. Trust me, testing react-native or react is such a PITA (Pain in the Ass) that you should consider going through Jest documentation seriously and primarily focus on the mock part.

Later you may very well encounter problems while setting up Jest for react-native or react and there the documentation will come in handy.

Here are some series of tutorials and references that helped me get started with Jest and unit testing react and react-native -

  1. Jest Documentation
  2. Testing React and React Native using Jest/Enzyme setup
  3. Reference article for Mocks, Stubs and Fakes
  4. Testing Redux - P1
  5. Testing Redux - P2
  6. Testing Redux - P3

Solution for the error after applying RNFirebaseMock

The error that you now are getting is because there doesn't exist a function named app under default export of your mock. So let create it.

Go to your mocks directory and open react-native-firebase-mock.js. look for export default class RNFirebase, inside that class there are several static methods with no implementation. Create one function doing nothing in the class with the name app.

Your default exported class should look something like this now -

export default class RNFirebase {
  static initializeApp() {
    RNFirebase.firebase = new MockFirebase()
    RNFirebase.promises = []
    return RNFirebase.firebase
  }

  static reset() {
    RNFirebase.promises = []
    RNFirebase.firebase.databaseInstance = null
  }

  static waitForPromises() {
    return Promise.all(RNFirebase.promises)
  }

  static analytics () {}

  static app () {}
}

This should do the trick, however I belive you are extensively using Firebase. In my case a mock implementation as simple as the one I gave you did the trick for me.

If you are extensively using most of the APIs of Firebase then you are bound to get more errors like you just saw because we haven't yet added mock implementations for all the APIs of RNFirebase in our Firebase mock.

If that case shall ever arise, I would suggest that you look at this mock implementation of Firebase which I guess covers the Firebase completely.

like image 80
Himanshu Singh Avatar answered Nov 15 '22 00:11

Himanshu Singh