6

I am writing an application with backend written as a node/express server running firestore commands through the Admin SDK on firebase functions. I'm wondering what the best way to test my database functions are. An example of such a function is this:

export const deleteDocument = async(id: string): Promise<void> => {
    try {
        await firestore.collection("sampleCollection").doc(id).delete();
    } catch (e) {
        throw new Error(`Could not delete ${id}`);
    }
}

I would then like to run a unit test such as this one (I know the actual logic here is a bit weird, but it's been done on the fly, and isn't really the focus of the question):

it('should delete a document from the sample collection', async () => {
    //This would already be tested
    const id = await createDocument(...);
    if (id !== undefined) {
      await deleteDocument(id);
      try {
        await getCollective(id);
        expect(true).toBe(false);
      } catch (e) {
        expect(true).toBe(true);
      }
    } else {
      expect(id).toBeDefined();
    }
});

I define my firestore instance like this:

import * as admin from 'firebase-admin';
const firebase = admin.initializeApp({credential: admin.credential.cert(...), ...otherConfig});
const firestore = firebase.firestore();
export {firebase, firestore};

This then leads to an initialized firebase application with admin priveleges. I then run firebase emulator:start --only firestore,functions, which fires up the backend on emulators. I can now run '/delete/:id' on an endpoint I've created on the express server, which runs the function deleteDocument. This works perfectly fine when I do it "manually" by triggering the function. The problem is when I want to run a test. For some reason, the test itself doesn't connect to the emulator, even if the FIREBASE_EMULATOR_PORT environment variable has been set to the correct value.

I did try and use @firebase/testing's .initializeAdminApp() method, but the firestore type from this method crashes with the firestore type of admin.initializeApp() from firestore-admin, which makes it look like I can't switch the database with a function inside the tests, like shown here. I'd also hope to avoid mocking the functions, and instead use the emulator for what it's worth.

So my problem is that I don't really know how to run the tests. If I do it while running the emulator, the tests get data from my production firestore, instead of the emulator, even though the express server on the function loads data correctly to the firestore emulator.

Any help is appreciated, and if you need more information, I'll be happy to give it.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
XBullet123
  • 471
  • 6
  • 20
  • Please don't write `async` functions that don't `await` and please read [What is the explicit promise construction antipattern and how do I avoid it?](https://stackoverflow.com/questions/23803743/what-is-the-explicit-promise-construction-antipattern-and-how-do-i-avoid-it/25569299#25569299) – Aluan Haddad Sep 04 '20 at 18:54
  • 3
    I'll edit the function, but as you can see, it's not strictly relevant. Thanks for the post though! – XBullet123 Sep 04 '20 at 18:56
  • same question... did you get an answer yet? – fotoflo Aug 30 '22 at 03:11
  • @fotoflo I ended up not testing the db functions directly, but mocked the calls to the actual DB in my code, since I "trust" that the firebase code does its job. – XBullet123 Aug 31 '22 at 15:07

0 Answers0