Test Firebase Cloud Functions Access Firestore Emulator (Node.js)

Setup Firebase Hosting and Functions (Node)

You want to install Firestore Emulator as well

firebase init     ######## #### ########  ######## ########     ###     ######  ########     ##        ##  ##     ## ##       ##     ##  ##   ##  ##       ##     ######    ##  ########  ######   ########  #########  ######  ######     ##        ##  ##    ##  ##       ##     ## ##     ##       ## ##     ##       #### ##     ## ######## ########  ##     ##  ######  ########You're about to initialize a Firebase project in this directory:  /code/firebase/journeyBefore we get started, keep in mind:  * You are currently outside your home directory  * You are initializing in an existing Firebase project directory? Which Firebase CLI features do you want to set up for this folder? Press Space to select features, then Enter to confirm your choices. Emulators: Set up local emulators for Firebase features=== Project SetupFirst, let's associate this project directory with a Firebase project.You can create multiple project aliases by running firebase use --add,but for now we'll just set up a default project.i  .firebaserc already has a default project, using journeyx.=== Emulators Setup? Which Firebase emulators do you want to set up? Press Space to select emulators, then Enter to confirm your choices. Functions, Firestore, Hostingi  Port for functions already configured: 5001? Which port do you want to use for the firestore emulator? 8080i  Port for hosting already configured: 5000? Would you like to download the emulators now? Yesi  firestore: downloading cloud-firestore-emulator-v1.11.2.jar...Progress: ======================================================> (100% of 90MB)i  Writing configuration info to firebase.json...i  Writing project information to .firebaserc...✔  Firebase initialization complete!

Start Firestore Emulator

firebase emulators:start --only firestore,functions

NOTE: firebase serve --only functions,firestore used to be supported, but now it shows Error: Please use firebase emulators:start to start the Realtime Database or Cloud Firestore emulators. firebase serve only supports Hosting and Cloud Functions.

NOTE: I tried running firebase emulators:start --only firestore followed by firebase serve, it complained of The Cloud Firestore emulator is not running, so calls to Firestore will affect production. Despite the warning, the testing seems to work, though I am not aware of any side effects.

Install Packages

npm install firebase-admin --savenpm istall @firebase/testing --save-dev

Create cloud functions to access Firestore Emulator.

Edit functions/index.js.

Option 1: using @firebase/testing

const isDev = process.env.FUNCTIONS_EMULATORconst functions = require('firebase-functions');let admin       // serverlet firebase    // testinglet firestorelet dbconst projectId = 'PROJECT_NAME'if (isDev) {  firebase = require("@firebase/testing")  db = firebase.initializeTestApp({ projectId: projectId }).firestore()  firestore = firebase.firestore  // admin = firebase}else {  admin = require('firebase-admin')  admin.initializeApp(functions.config().firebase)  db = admin.firestore()  firestore = admin.firestore  // firebase = admin}// exports.requestInvite = functions.https.onRequest(async (req, res) => {exports.requestInvite = functions.https.onCall(async (data, context) => {  const email = data.email  // use email as docId  const docId = Buffer.from(email).toString('base64')  const docRef = db.collection('request_invite').doc(docId)  if (isDev) {    // optional - delete database    await firebase.clearFirestoreData({ projectId })  }  const doc = await docRef.get()  if (doc.exists) {    console.log('doc exist', doc.data())  }  await docRef.set({    created: firestore.Timestamp.now(),    email: email  })  return {    text: `Hello ${email}!`,    docId: docRef.id  }})

NOTE: Refer to onRequest vs onCall.

NOTE: Bear in mind @firebase/testing is a client side package, so data type such as firestore.Timestamp cannot be mixed with firebase-admin which is a server package.

Option 2: firebase-admin only

const functions = require('firebase-functions');const admin = require('firebase-admin')admin.initializeApp(functions.config().firebase)const db = admin.firestore()const firestore = admin.firestoreexports.requestInvite = functions.https.onCall(async (data, context) => {  const email = data.email  // use email as docId  const docId = Buffer.from(email).toString('base64')  const docRef = db.collection('request_invite').doc(docId)  const doc = await docRef.get()  if (doc.exists) {    console.log('doc exist', doc.data())  }  await docRef.set({    created: created: firestore.Timestamp.now(),    email: email  })  return {    text: `Hello ${email}!`,    docId: docRef.id  }})

If you have Cloud Functions that use the Firebase Admin SDK to write to Cloud Firestore, these writes will be sent to the Cloud Firestore emulator if it is running. If further Cloud Functions are triggered by those writes, they will be run in the Cloud Functions emulator. - Source

NOTE: Once emulator is stopped, all data are automatically cleared.

References:

❤️ Is this article helpful?

Buy me a coffee ☕ or support my work via PayPal to keep this space 🖖 and ad-free.

Do send some 💖 to @d_luaz or share this article.

✨ By Desmond Lua

A dream boy who enjoys making apps, travelling and making youtube videos. Follow me on @d_luaz

👶 Apps I built

Travelopy - discover travel places in Malaysia, Singapore, Taiwan, Japan.