javascriptfirebasereact-nativejes

how to test react native code with jest and mock for firebase


I am trying to test react native method using jest , my problem is the revised value is not the same as expected value . because the function use firebase i made mock so this is the method i want to use

 insertUserAction= async  ()=>{
 console.log("inside inserUserAction")
 var userActionKey =firebase.database().ref().child('userActions').push().key;
 firebase.database().ref('userActions/'+userActionKey).set(
  {

  userID: firebase.auth().currentUser.uid,
  ActionID:'001',
  time:new Date().getHours(),
  day:moment().format('dddd'),
  Repetition:'1',
  inRoutine:'0',
  insertedDate: new Date().getFullYear()+'/'+new Date().getMonth()+'/'+new Date().getDate(),
  })

  .then(() => {
    console.log("enter then");

    this.setState(() =>{
      return {
      userID:firebase.auth().currentUser.uid,
      ActionID:'001',
      time:new Date().getHours(),
      day:moment().format('dddd'),
      Repetition:'1'}
    });
      console.log('inserted')
  }).catch((error)=>{
      console.log(error)
  });
 }

and here the firebase configuration

   const firebaseConfig = {


  apiKey: "******",
  authDomain: "*****",
  databaseURL: "*****",
  projectId: "*****",
  storageBucket: "*******",
  messagingSenderId: "******",
  appId: "*****",
  };

and here the test

    import React from 'react';
    import HomeScreen from     '../screens/HomeScreen';

   import renderer from 'react-test-renderer';

  jest.mock("firebase/app", () => {
  const data = { ActionID: "unnamed" };
  const snapshot = { val: () => data };
  return {
    firebaseConfig: jest.fn().mockReturnValue({
    database: jest.fn().mockReturnValue({
      ref: jest.fn().mockReturnThis(),
      once: jest.fn(() => Promise.resolve(snapshot))
    })
  })
};
 });

test('testing Analysis feature ', () => {
 const component = renderer.create(<HomeScreen ActionID="5" />);
 const instance = component.getInstance();
 instance.insertUserAction();
 expect(instance.state.ActionID).toBe("001");
  });

I am not sure with the mock


Solution

  • As you can see, it's not necessary to mock the firebaseConfig, because this is only needed to connect to real db, but for mock purpose it not needed, so basically you only need to mock what you really need, in this case you need something like this:

    jest.mock("firebase/app", () => {
      const data = { ActionID: "unnamed" };
      const snapshot = { val: () => data };
      return {
        firebaseConfig: jest.fn().mockReturnValue({}),
        auth: jest.fn().mockReturnValue({ currentUser: { uid: 'uid' } }),
        database: jest.fn().mockReturnValue({
          ref: jest.fn().mockImplementation(() => ({
            child: jest.fn().mockImplementation(() => ({
              push: jest.fn().mockReturnValue({
                key: 'someValueAsKey'
              })
            })),
            set: jest.fn(),
          })),
          once: jest.fn(() => Promise.resolve(snapshot))
        })
      };
    });
    

    I kept the firebaseConfig mock, because I didn't want to remove your code, if you want you can remove it.

    remember that you can use some firebase mock libraries, like this one https://www.npmjs.com/package/firebase-mock

    I hope this can help you.