I am reading how to mock google cloud functions for firebase and have issues of properly mocking the following code:
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
var db = admin.firestore();
The example in the link uses the following code to mock initializeApp which does work
admin = require('firebase-admin');
adminInitStub = sinon.stub(admin, 'initializeApp');
Now admin.firestore is defined in firebase-namespace.js as following:
Object.defineProperty(FirebaseNamespace.prototype, "firestore", {
    get: function () {
        var ns = this;
        var fn = function (app) {
            return ns.ensureApp(app).firestore();
        };
        return Object.assign(fn, require('@google-cloud/firestore'));
    },
    enumerable: true,
    configurable: true
});
I've tried various things to stub this but I fail
Results in firestore is not a function:
    Object.defineProperty(admin, "firestore", {
        get: function () {
            return 32;
        }
    });
Does not mock firestore() at all and calls the original function which fails hard:
    sinon.stub(admin, 'firestore').returns({get() { }});
TypeError: Cannot stub non-existent own property get
   firestoreStub = sinon.stub(admin.firestore, 'get').callsFake(function () {return {data:"Foo"}});
I lack understanding what admin.firebase() actually is. It does not look like it is a property because AFAI when I mock a getter of a property, I would call admin.firebase and not a function admin.firebase(). But it is also not mockable via a function.
That really took me too long.
To be able to mock the admin.firebase() the getter function of the property should actually return a function. 
My initial assumption was that firebase() is a function, which it was not. Then by looking at the implementation I understood that this is a property with a custom getter. However I tried to return some json data block via the getter.
I initially failed to understand that admin.firestore is indeed a property but I was missing the key on why I have to call the property as a function, which is typically not needed on the property itself.
After getting to the point I understood that the getter of the property actually returned a function and that the admin.firebase() can be read like
var method = admin.firebase; // calling the property getter function
method(); // assuming the getter returned a function object
So for my future self ;) this does the trick:
sinon.stub(admin, 'firestore')
   .get(function() { 
       return function() { 
           return "data";
       }
   });
Originally I was trying to do
sinon.stub(admin, 'firestore').get( function () { return "data"; } ); which failed because the admin.firestore() ultimately yielded in "data"(), which made no sense.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With