How To Initialise Firebase Admin in Vitest

How to set up Firebase Admin to work perfectly in a separate Vitest Suite.

FirebaseVitestTesting

In this tutorial, you will learn:

  1. How to use the same Firebase Admin you use in your Firebase Functions directory in your Separate test directory.
  2. How to initialise Firebase Admin correctly in Vitest.

Setting up a Vitest test suite for a Firebase project is a relatively rare occurrence, which is why you often forget how to do it. Well, no longer! Bookmark this page and you’ll always be one click away.

Step 1 — Use an Alias To Your Function Directory’s Firebase Admin

You should keep your tests separate from your /functions directory, as everything in /functions is pushed to the Cloud Run container, including /node_module. However, there is one small predicament with this: you need to have a new package.json and a new set of /node_modules.

If your tests require you to set or check state in Firebase emulators, you’ll need firebase-admin. But having two versions of this package installed, one in /functions and one elsewhere, can cause package-mismatch errors. To get around this, you need to use a Vitest Alias.

I typically use the root of the Firebase project, one level above , /functions as my second node project. So, to add my alias, I run the following from the root:

bash
touch vitest.config.ts

I then paste in the following code:

javascript
import { defineConfig } from "vitest/config";
import path from "path";

export default defineConfig({
  resolve: {
    alias: {
      "firebase-admin": path.resolve(
        __dirname,
        "functions/node_modules/firebase-admin"
      ),
    },
  },
});

This tells Vitest to look for firebase-admin inside of my /functions directory’s node_modules.

If your second node project is in a different location, you should change the value assigned to the "firebase-admin" key.

Step 2 — Initialise Admin

You can either connect firebase-admin to your local Firebase emulator or to your live Firebase project. I’ll explain both here.

Connect to Firebase Emulators

At the top of your test file, paste the following code:

typescript
admin.initializeApp({
  projectId: "<your-project-id>",
});

admin.firestore().settings({
  host: "127.0.0.1:8180", // Firestore emulator host
  ssl: false, // Disable SSL since you're connecting to the emulator
});

// Connect to Storage emulator
process.env.FIREBASE_STORAGE_EMULATOR_HOST = "127.0.0.1:9199";

The host values in the settings for firestore tell the firebase-admin instance where to make its API calls. 127.0.0.1 is your localhost. Similarly for the env variable for storage.

If you’re running your emulators from different ports, you’ll need to change the ports on the addresses. For example, if you’re running storage from port 9198, the address will change to 127.0.0.1:9198.

If you’re running more emulators, you’ll need to add further settings or env alterations here too.

Connect to a Firebase Project

The easiest way to do this is with a Firebase Service Account Key. You can read about how to get one here:

Create a Firebase Service Account Key

To initialise firebase-admin with this key, add the following code to the top of your file:

typescript
const serviceAccount = require("path/to/your/key.json");

This automatically sets up everything for you.

Final Words

That’s it! I hope this saves you the annoying 20-minute hassle of remembering how to do this. It’s an infrequent time-saving, but a blessed one. Happy Firebaseing!