Unit testing of Cloud Functions Stay organized with collections Save and categorize content based on your preferences.
This page describes best practices and tools for writing unit tests for yourfunctions, such as tests that would be a part of a Continuous Integration (CI)system. To make testing easier, Firebase provides theFirebase Test SDK forCloud Functions. Itis distributed on npm asfirebase-functions-test, and is a companion test SDKtofirebase-functions. TheFirebase Test SDK forCloud Functions:
- Takes care of the appropriate setup and teardown for your tests, such assetting and unsetting environment variables needed by
firebase-functions. - Generates sample data and event context, so that you only have to specifythe fields that are relevant to your test.
firebase-functions-test can only be used with functions written withfirebase-functions 2.0.0 or above.Test setup
Install bothfirebase-functions-test andMocha, atesting framework, by running the following commands in your functions folder:
npm install --save-dev firebase-functions-testnpm install --save-dev mochaNext create atest folder inside the functions folder, create a new fileinside it for your test code, and name it something likeindex.test.js.
Finally, modifyfunctions/package.json to add the following:
"scripts": { "test": "mocha --reporter spec"}Once you have written the tests, you can run them by runningnpm test insideyour functions directory.
InitializingFirebase Test SDK forCloud Functions
There are two ways to usefirebase-functions-test:
- Online mode (recommended): Write tests that interact with a Firebase projectdedicated to testing so that database writes, user creates, etc. would actuallyhappen, and your test code can inspect the results. This also means that otherGoogle SDKs used in your functions will work as well.
- Offline mode: Write siloed and offline unit tests with no side effects.This means that any method calls that interact with a Firebase product (e.g.writing to the database or creating a user) need to be stubbed. Using offlinemode is generally not recommended if you haveCloud Firestore orRealtime Databasefunctions, since it greatly increases the complexity of your test code.
Initialize SDK in online mode (recommended)
If you would like to write tests that interact with a test project, you need tosupply the project config values that are needed for initializing the app throughfirebase-admin, and the path to a service account key file.
To get your Firebase project's config values:
- Open your project settings in theFirebase console.
- InYour apps, select the desired app.
In the right pane, select the option to download a configuration filefor Apple and Android apps.
For web apps, selectConfig to displayconfiguration values.
To create a key file:
- Open theService Accounts paneof theGoogle Cloud console.
- Select theApp Engine default service account, and use the options menu atthe right to selectCreate key.
- When prompted, select JSON for the key type, and clickCreate.
After saving the key file, initialize the SDK:
//Atthetopoftest/index.test.js//MakesuretousevaluesfromyouractualFirebaseconfigurationconsttest=require('firebase-functions-test')({databaseURL:'https://PROJECT_ID.firebaseio.com',storageBucket:'PROJECT_ID.firebasestorage.app ',projectId:'PROJECT_ID',},'path/to/serviceAccountKey.json');Initialize SDK in offline mode
If you would like to write completely offline tests, you can initialize the SDKwithout any parameters:
//Atthetopoftest/index.test.jsconsttest=require('firebase-functions-test')();Mocking config values
If you usefunctions.config() in your functions code, you can mock the configvalues. For example, iffunctions/index.js contains the following code:
constfunctions=require('firebase-functions/v1');constkey=functions.config().stripe.key;Then you can mock the value inside your test file like so:
// Mock functions config valuestest.mockConfig({stripe:{key:'23wr42ewr34'}});Importing your functions
To import your functions, userequire to import your main functions file as amodule.Be sure to only do this after initializingfirebase-functions-test,and mocking config values.
//afterfirebase-functions-testhasbeeninitializedconstmyFunctions=require('../index.js');//relativepathtofunctionscodeIf you initializedfirebase-functions-test inoffline mode, and you haveadmin.initializeApp() in your functions code, then you need to stub it beforeimporting your functions:
//Ifindex.jscallsadmin.initializeAppatthetopofthefile,//weneedtostubitoutbeforerequiringindex.js.Thisisbecausethe//functionswillbeexecutedasapartoftherequireprocess.//Herewestubadmin.initializeApptobeadummyfunctionthatdoesn't do anything.adminInitStub=sinon.stub(admin,'initializeApp');//Nowwecanrequireindex.jsandsavetheexportsinsideanamespacecalledmyFunctions.myFunctions=require('../index');
Testing background (non-HTTP) functions
The process for testing non-HTTP functions involves the following steps:
- Wrap the function you would like to test with the
test.wrapmethod - Construct test data
- Invoke the wrapped function with the test data you constructed and any eventcontext fields you'd like to specify.
- Make assertions about behavior.
First wrap the function you'd like to test. Let's say you have a function infunctions/index.js calledmakeUppercase, which you'd like to test. Write thefollowing infunctions/test/index.test.js
//"Wrap"themakeUpperCasefunctionfromindex.jsconstmyFunctions=require('../index.js');constwrapped=test.wrap(myFunctions.makeUppercase);wrapped is a function which invokesmakeUppercase when it is called.wrappedtakes 2 parameters:
- data (required): the data to send to
makeUppercase. This directlycorresponds to the first parameter sent to the function handler that youwrote.firebase-functions-testprovides methods for constructing customdata or example data. - eventContextOptions (optional): fields of the event context that you'dlike to specify. The event context is the second parameter sent to thefunction handler that you wrote. If you do not include an
eventContextOptionsparameter when callingwrapped, an event context is still generatedwith sensible fields. You can override some of the generated fields byspecifying them here. Note that you only have to include the fields thatyou'd like to override. Any fields that you did not override are generated.
constdata=…//Seenextsectionforconstructingtestdata//Invokethewrappedfunctionwithoutspecifyingtheeventcontext.wrapped(data);//Invokethefunction,andspecifyparamswrapped(data,{params:{pushId:'234234'}});//Invokethefunction,andspecifyauthandauthType(forrealtimedatabasefunctionsonly)wrapped(data,{auth:{uid:'jckS2Q0'},authType:'USER'});//Invokethefunction,andspecifyallthefieldsthatcanbespecifiedwrapped(data,{eventId:'abc',timestamp:'2018-03-23T17:27:17.099Z',params:{pushId:'234234'},auth:{uid:'jckS2Q0'//onlyforrealtimedatabasefunctions},authType:'USER'//onlyforrealtimedatabasefunctions});Constructing test data
The first parameter of a wrapped function is the test data to invoke the underlyingfunction with. There are a number of ways to construct test data.
Using custom data
firebase-functions-test has a number of functions for constructing data neededto test your functions. For example, usetest.firestore.makeDocumentSnapshotto create a FirestoreDocumentSnapshot. The first argument is the data, and thesecond argument is the full reference path, and there is anoptional third argumentfor other properties of the snapshot you can specify.
//Makesnapshotconstsnap=test.firestore.makeDocumentSnapshot({foo:'bar'},'document/path');//Callwrappedfunctionwiththesnapshotconstwrapped=test.wrap(myFunctions.myFirestoreDeleteFunction);wrapped(snap);If you are testing anonUpdate oronWrite function, you'll need to createtwo snapshots: one for the before state and one for the after state. Then, youcan use themakeChange method to create aChange object with these snapshots.
//MakesnapshotforstateofdatabasebeforehandconstbeforeSnap=test.firestore.makeDocumentSnapshot({foo:'bar'},'document/path');//MakesnapshotforstateofdatabaseafterthechangeconstafterSnap=test.firestore.makeDocumentSnapshot({foo:'faz'},'document/path');constchange=test.makeChange(beforeSnap,afterSnap);//CallwrappedfunctionwiththeChangeobjectconstwrapped=test.wrap(myFunctions.myFirestoreUpdateFunction);wrapped(change);See theAPI reference for similar functionsfor all the other data types.
Using example data
If you don't need to customize the data used in the your tests, thenfirebase-functions-test offers methods for generating example data for eachfunction type.
//ForFirestoreonCreateoronDeletefunctionsconstsnap=test.firestore.exampleDocumentSnapshot();//ForFirestoreonUpdateoronWritefunctionsconstchange=test.firestore.exampleDocumentSnapshotChange();See theAPI reference for methods forgetting example data for every function type.
Using stubbed data (for offline mode)
If you initialized the SDK in offline mode, and are testing aCloud Firestore orRealtime Database function, you should use a plain object with stubsinstead of creating an actualDocumentSnapshot orDataSnapshot.
Let's say you are writing a unit test for the following function:
//Listensfornewmessagesaddedto/messages/:pushId/originalandcreatesan//uppercaseversionofthemessageto/messages/:pushId/uppercaseexports.makeUppercase=functions.database.ref('/messages/{pushId}/original').onCreate((snapshot,context)=>{//GrabthecurrentvalueofwhatwaswrittentotheRealtimeDatabase.constoriginal=snapshot.val();functions.logger.log('Uppercasing',context.params.pushId,original);constuppercase=original.toUpperCase();//YoumustreturnaPromisewhenperformingasynchronoustasksinsideaFunctionssuchas//writingtotheFirebaseRealtimeDatabase.//Settingan"uppercase"siblingintheRealtimeDatabasereturnsaPromise.returnsnapshot.ref.parent.child('uppercase').set(uppercase);});
Inside of the function,snap is used twice:
snap.val()snap.ref.parent.child('uppercase').set(uppercase)
In test code, create a plain object where both of these code paths will work,and useSinon to stub the methods.
//Thefollowinglinescreatesafakesnapshot,'snap',whichreturns'input'whensnap.val()iscalled,//andreturnstruewhensnap.ref.parent.child('uppercase').set('INPUT')iscalled.constsnap={val:()=>'input',ref:{parent:{child:childStub,}}};childStub.withArgs(childParam).returns({set:setStub});setStub.withArgs(setParam).returns(true);
Making assertions
After initializing the SDK, wrapping the functions, and constructing data, youcan invoke the wrapped functions with the constructed data and make assertionsabout behavior. You can use a library such asChai formaking these assertions.
Making assertions in online mode
If you initialized theFirebase Test SDK forCloud Functions inonline mode, youcan assert that the desired actions (such as a database write) has taken place byusing thefirebase-admin SDK.
The example below asserts that 'INPUT' has been written into the database of thetest project.
//CreateaDataSnapshotwiththevalue'input'andthereferencepath'messages/11111/original'.constsnap=test.database.makeDataSnapshot('input','messages/11111/original');//WrapthemakeUppercasefunctionconstwrapped=test.wrap(myFunctions.makeUppercase);//Callthewrappedfunctionwiththesnapshotyouconstructed.returnwrapped(snap).then(()=>{//Readthevalueofthedataatmessages/11111/uppercase.Because`admin.initializeApp()`is//calledinfunctions/index.js,there's already a Firebase app initialized. Otherwise, add//`admin.initializeApp()`beforethisline.returnadmin.database().ref('messages/11111/uppercase').once('value').then((createdSnap)=>{//Assertthatthevalueistheuppercasedversionofourinput.assert.equal(createdSnap.val(),'INPUT');});});
Making assertions in offline mode
You can make assertions about the expected return value of the function:
constchildParam='uppercase';constsetParam='INPUT';//Stubsareobjectsthatfakeand/orrecordfunctioncalls.//Theseareexcellentforverifyingthatfunctionshavebeencalledandtovalidatethe//parameterspassedtothosefunctions.constchildStub=sinon.stub();constsetStub=sinon.stub();//Thefollowinglinescreatesafakesnapshot,'snap',whichreturns'input'whensnap.val()iscalled,//andreturnstruewhensnap.ref.parent.child('uppercase').set('INPUT')iscalled.constsnap={val:()=>'input',ref:{parent:{child:childStub,}}};childStub.withArgs(childParam).returns({set:setStub});setStub.withArgs(setParam).returns(true);//WrapthemakeUppercasefunction.constwrapped=test.wrap(myFunctions.makeUppercase);//Sincewe've stubbed snap.ref.parent.child(childParam).set(setParam) to return true if it was//calledwiththeparametersweexpect,weassertthatitindeedreturnedtrue.returnwrapped(snap).then(makeUppercaseResult=>{returnassert.equal(makeUppercaseResult,true);});
You can also usedSinon spies toassert that certain methods have been called, and with parameters you expect.
Testing HTTP functions
To test HTTP onCall functions, use the same approach astesting background functions.
If you are testing HTTP onRequest functions, you should usefirebase-functions-test if:
- You use
functions.config() - Your function interacts with a Firebase project or other Google APIs, andyou'd like to use a real Firebase project and its credentials for your tests.
An HTTP onRequest function takes two parameters: a request object and a responseobject. Here is how you might test theaddMessage() example function:
- Override the redirect function in the response object, since
sendMessage()calls it. - Within the redirect function, usechai.assertto help make assertions about what parameters the redirect function shouldbe called with:
//Afakerequestobject,withreq.query.textsetto'input'constreq={query:{text:'input'}};//Afakeresponseobject,withastubbedredirectfunctionwhichassertsthatitiscalled//withparameters303,'new_ref'.constres={redirect:(code,url)=>{assert.equal(code,303);assert.equal(url,'new_ref');done();}};//InvokeaddMessagewithourfakerequestandresponseobjects.Thiswillcausethe//assertionsintheresponseobjecttobeevaluated.myFunctions.addMessage(req,res);
Test cleanup
At the very end of your test code, call the cleanup function. This unsetsenvironment variables that the SDK set when it was initialized, and deletesFirebase apps that may have been created if you used the SDK to create a realtime databaseDataSnapshot or FirestoreDocumentSnapshot.
test.cleanup();Review complete examples and learn more
You can review the complete examples on the Firebase GitHub repository.
- TestingRealtime Database and HTTP Functions in Online Mode
- TestingRealtime Database and HTTP Functions in Offline Mode
To learn more, refer to theAPI referenceforfirebase-functions-test.
Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.
Last updated 2026-02-18 UTC.