Simple way to use ts-firebase-driver-testing with a Jest mock

While working at Freetrade, I made the ts-firebase-driver-testing library to allow rapid testing and debugging of Firebase applications (other engineers have contributed to it since then).

The initial plan with the library was to abstract out the Firebase SDK as a set of plain interfaces, and then provide a single-process in-memory implementation of those interfaces. This worked fine and it does let you swap out Firebase when running tests, which was the main goal.

I later realised that there’s a much easier way to use the in-process implementation in tests by using a Jest mock. You just need to apply the Jest mock before the Firebase SDK gets imported or initialised.

For example:

// Important: this must come before the "firebase-admin" import line.
// Either place this at the top of a test file, or in a setup file that Jest
// will call before the whole test suite.
import { InProcessFirebaseDriver } from "ts-firebase-driver-testing";

const inProcessFirebase = new InProcessFirebaseDriver();
jest.mock("firebase-admin", () => {
  return {
    firestore: () => inProcessFirebase.firestore(),
  };
});

That’s it for mocking out Firestore. Nothing else is needed and no implementation code has to change.

Now you can use Firestore as normal in both implementation and test code:

import admin from "firebase-admin";

export const foobarFunction = async () => {
    await admin
      .firestore()
      .collection("things")
      .doc("12345")
      .set({foo: "bar"});
}

You can also mock out firebase-functions to cover more functionality:

jest.mock("firebase-functions", () => {
  return {
    region: () => inProcessFirebase.runWith().region(),
    config: () => ({
      foobar: {
        foo: "bar",
      },
    }),
    logger: {
      info: jest.fn(),
      error: jest.fn(),
    }
  };
});

You can put these Jest mocks at the top of test files to do it only for certain tests, or you can do it in a setup.ts that Jest can be configured to run before the whole test suite.

This is much more straightforward than messing around with the various interfaces from the ts-firebase-driver-testing library. It also means you can test existing Firebase application code without touching the implementation code or doing anything different in the test, but get the benefit of fast, in-process testing and debugging.

By the way, you can hire me as a freelance Firebase developer to assist with your Firebase project.