user9813762
user9813762

Reputation:

Test Firebase RealtimeDatabase using Jest

My purpose is simply to test one function. I cannot figure out how to mock firebase properly. I try to keep the example with axios mocking from Jest docs. I have the following code:

MusicService.js

import { initializeApp } from "firebase/app";
import "firebase/database";

const firebase = initializeApp({
  apiKey: "<API_KEY>",
  authDomain: "<PROJECT_ID>.firebaseapp.com",
  databaseURL: "https://<DATABASE_NAME>.firebaseio.com",
  projectId: "<PROJECT_ID>",
  storageBucket: "<BUCKET>.appspot.com",
  messagingSenderId: "<SENDER_ID>",
});

export class MusicService {
  static getAlbums() {
    return firebase.database().ref("albums").once("value")
    .then(snapshot => Object.values(snapshot.val()));
  }
}

MusicService.test.js

import firebase from 'firebase/app';
import 'firebase/database';
import { MusicService } from './MusicService';

jest.mock('firebase/app');
jest.mock('firebase/database');

test("test", () => {
  firebase.initializeApp.mockImplementation(() => {
    database: jest.fn(() => {
      return {
        ref: jest.fn()
      }
    })
  });

  MusicService.getAlbums();
});

The problem is that I get the following error: enter image description here

I tried to mock firebase.database.

test("test", () => {
  firebase.mockImplementation(() => {
    return {
      database: {

      }
    }
  });
  MusicService.getAlbums();
});

But in this case I get the error that says:

TypeError: _app.default.mockImplementation is not a function.

I don't expect the working example will be given, but rather could you tell please, what exactly should I mock? The whole firebase library or maybe the part where my function starts - return firebase.database().

Upvotes: 7

Views: 5100

Answers (2)

Defrian
Defrian

Reputation: 660

this is my current mock implementation for firebase.js. for me it is working fine.

const firebase = jest.genMockFromModule('firebase');

firebase.initializeApp = jest.fn();

const data = { name: 'data' };
const snapshot = { val: () => data, exportVal: () => data, exists: jest.fn(() => true) };

firebase.database = jest.fn().mockReturnValue({
  ref: jest.fn().mockReturnThis(),
  on: jest.fn((eventType, callback) => callback(snapshot)),
  update: jest.fn(() => Promise.resolve(snapshot)),
  remove: jest.fn(() => Promise.resolve()),
  once: jest.fn(() => Promise.resolve(snapshot)),
});

firebase.auth = jest.fn().mockReturnValue({
  currentUser: true,
  signOut() {
    return Promise.resolve();
  },
  signInWithEmailAndPassword(email, password) {
    return new Promise((resolve, reject) => {
      if (password === 'sign' || password === 'key') {
        resolve({ name: 'user' });
      }
      reject(Error('sign in error '));
    });
  },
  createUserWithEmailAndPassword(email, password) {
    return new Promise((resolve, reject) => {
      if (password === 'create' || password === 'key') {
        resolve({ name: 'createUser' });
      }
      reject(Error('create user error '));
    });
  },
});

export default firebase;

Upvotes: 4

user9813762
user9813762

Reputation:

I have figured out. I should mock only those modules, a function I am going to test, depends on. For example, I want to test getAlbums function. It uses initializeApp function which is imported from firebase/app module in MusicService.js. So when initializeApp function is being called it should return an object containing database function which in turn returns an object with ref and once functions. Code:

MusicService.test.js.

import { MusicService } from "./FirebaseService";

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

test("getAlbums function returns an array", async () => {
  const data = await MusicService.getAlbums();
  expect(data.constructor).toEqual(Array);
});

Upvotes: 9

Related Questions