How to test Firebase with Jest

 by Robin Wieruch
 - Edit this Post
firebase test, firebase testing, firebase jest, firebase mock

Every time I used Firebase, I ran into the problem of how to test Firebase's database and authentication. Since I am using Jest as my default testing environment, I figured everything I needed already comes with Jest. In this tutorial, you will learn how to mock Firebase's features. We will use Firebase Admin SDK for the Firebase setup, however, the same works with the traditional client-side Firebase using Firebase Real-Time Database, Firebase Firestore, and Firebase Authentication.

import * as firebaseAdmin from 'firebase-admin';
import firebaseServiceAccountKey from './firebaseServiceAccountKey.json';
if (!firebaseAdmin.apps.length) {
firebaseAdmin.initializeApp({
credential: firebaseAdmin.credential.cert(
firebaseServiceAccountKey
),
databaseURL: 'https://my-firebase-application.firebaseio.com',
});
}
export default firebaseAdmin;

After setting up Firebase, we have our first database function which creates a record in Firebase's database:

import firebaseAdmin from './firebase';
export const createCourse = async ({
uid,
courseId,
bundleId,
amount,
paymentType,
}) => {
await firebaseAdmin
.database()
.ref(`users/${uid}/courses`)
.push()
.set({
courseId: courseId,
packageId: bundleId,
invoice: {
createdAt: firebaseAdmin.database.ServerValue.TIMESTAMP,
amount,
licensesCount: 1,
currency: 'USD',
paymentType,
},
});
return true;
}

In our test file, a test with Jest could be similar to this one for testing the Firebase function:

import { createCourse } from './';
import firebaseAdmin from './firebase';
describe('createFreeCourse', () => {
it('creates a course', async () => {
const set = firebaseAdmin
.database()
.ref()
.push().set;
const result = createCourse(
'1',
'THE_ROAD_TO_GRAPHQL',
'STUDENT',
0,
'FREE'
);
await expect(result).resolves.toEqual(true);
expect(set).toHaveBeenCalledTimes(1);
expect(set).toHaveBeenCalledWith({
courseId: 'THE_ROAD_TO_GRAPHQL',
packageId: 'STUDENT',
invoice: {
createdAt: 'TIMESTAMP',
amount: 0,
licensesCount: 1,
currency: 'USD',
paymentType: 'FREE',
},
});
});
});

Before this test can run through, we need to mock Firebase in the test file to cover the problematic lines (highlighted). Instead of mocking Firebase as library, we mock the setup which happens in another file which I have shown before:

import { createCourse } from './';
import firebaseAdmin from './firebase';
jest.mock('./firebase', () => {
const set = jest.fn();
return {
database: jest.fn(() => ({
ref: jest.fn(() => ({
push: jest.fn(() => ({
set,
})),
})),
})),
};
});
describe('createFreeCourse', () => {
...
});

Now it's possible to call Jest's toHaveBeenCalledTimes() and toHaveBeenCalledWith() on the mocked function. However, we still didn't mock the Firebase timestamp properly. In our source code, let's use the explicit Firebase import rather than our Firebase setup for the timestamp:

import * as firebaseAdminVanilla from 'firebase-admin';
import firebaseAdmin from './firebase';
export const createCourse = async ({
uid,
courseId,
bundleId,
amount,
paymentType,
}) =>
await firebaseAdmin
.database()
.ref(`users/${uid}/courses`)
.push()
.set({
courseId: courseId,
packageId: bundleId,
invoice: {
createdAt: firebaseAdminVanilla.database.ServerValue.TIMESTAMP,
amount,
licensesCount: 1,
currency: 'USD',
paymentType,
},
});

Now, we can Jest mock the Firebase import for the Firebase constant in our test:

import { createCourse } from './';
import firebaseAdmin from './firebase';
jest.mock('firebase-admin', () => {
return {
database: {
ServerValue: {
TIMESTAMP: 'TIMESTAMP',
},
},
};
});
jest.mock('./firebase', () => {
...
});
describe('createFreeCourse', () => {
...
});

The Firebase constant should be alright in our test assertion now. Also you could consider moving the last Firebase mock into your jest.setup.js file, because it may be needed for other unit and integration tests as well. After all, you should have everything at your hands to test Firebase applications now.

Keep reading about 

Those who follow my content know that I always use the good old Firebase Realtime Database in React applications. I am saying good old here, because there is this new cool kid on the block: Firebase…

Interested in reading this tutorial as one of many chapters in my advanced React with Firebase book? Checkout the entire The Road to React with Firebase book that teaches you to create business web…

The Road to React

Learn React by building real world applications. No setup configuration. No tooling. Plain React in 200+ pages of learning material. Learn React like 50.000+ readers.

Get it on Amazon.