Search code examples
node.jsgoogle-cloud-firestoresinonstubsinon-chai

How to mock firestore query with mocha and sinon?


W.r.t. How to mock firestore with mocha how do I mock the following firestore query using sinon?

import * as admin from "firebase-admin";
const db: FirebaseFirestore.Firestore = admin.firestore();
const storeSnapshot: = await db
        .doc(`/Client/${clientId}/Store/${storeId}`)
        .get();

I tried:

import * as _sinon from 'sinon';

it('Query Client collection not empty test', async () => {

const clientStoreDocStub = _sinon.stub(db, "doc");
clientStoreDocStub.withArgs("/Client/123/Store/789").resolves({
            id: "789",
            settings: [ {setting1: "Setting1-value", setting2: "Setting2-value"}, {setting1: "Setting3-value", setting2: "Setting4-value"}]
        });
clientStoreDocStub.withArgs("/Client/456/Store/012").resolves({
            id: "012",
            settings: [ {setting1: "Setting5-value", setting2: "Setting6-value"}, {setting1: "Setting7-value", setting2: "Setting8-value"}]
        });        
const storeSnapshot: FirebaseFirestore.DocumentSnapshot = await db
              .doc("/Client/123/Store/789")
              .get();
const store = storeSnapshot.data();
});

but get the following error:

  1) Mock firebase firestore Tests
       Query Client collection not empty test:
     TypeError: dbInit_1.db.doc(...).get is not a function

Solution

  • import * as _chai from "chai";
    import * as chaiAsPromised from "chai-as-promised";
    import * as admin from "firebase-admin";
    import * as _sinon from 'sinon';
    _chai.use(chaiAsPromised);
    var expect = _chai.expect;
    const db: FirebaseFirestore.Firestore = admin.firestore();
    
    describe("Test with mock firestore", () => {
        var docRefStub;
        beforeEach(() => { docRefStub = _sinon.stub(db, "doc");});
        afterEach(() => {db.doc.restore();});
        it("Test should pass with valid request params", async () => {
            const expectedString = "Hello World!!!";
            const testCollection = {
                "/Client/123/Store/789": {
                     data: 1,
                     moreData: "Hello World!!!"
                }
            }
            const setSpy = _sinon.spy();
            docRefStub.callsFake(fakeFsDoc(testCollection, setSpy));
            await callAFunction("123", "789");
            expect(setSpy.called).to.be.true;
            expect(setSpy.getCall(0).args[0].data).to.not.be.null;
            expect(setSpy.getCall(0).args[0].moreData).to.deep.equal(expectedString);
        }
    });
    
    export function fakeFsDoc(database, setSpy = null) {
        return docId => {
            const data = database[docId] ?? undefined;
            return {
                get: async () => ({
                   data: () => data
                }),
                set: setSpy
            }
        }
    }