Skip to content

Instantly share code, notes, and snippets.

@pejalo
Last active April 7, 2020 13:49
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pejalo/53fa075ef0e873431b606d322dcfadd5 to your computer and use it in GitHub Desktop.
Save pejalo/53fa075ef0e873431b606d322dcfadd5 to your computer and use it in GitHub Desktop.
Setup for testing HTTP-triggered Firebase Functions locally
const functions = require('firebase-functions'); // To stub config()
const admin = require('firebase-admin'); // To get credential cert for initializeApp
const firebase = require('firebase'); // To sign in test user and test database writes
const assert = require('chai').assert;
const sinon = require('sinon');
// https://firebase.google.com/docs/functions/unit-testing
// The functions make use of 'firebase-admin', whereas client-side code uses 'firebase'.
// We initialze 'firebase' here to mock client-side code.
// 'firebase-admin' is only needed here to generate the credential for stubbing 'functions',
// and should not be initialized here.
describe('functions', function () {
var myFunctions;
var configStub;
var authToken;
before(done => {
// Load config
const serviceAccount = require('./config/serviceAccountKey.json');
const firebaseConfig = require('./config/firebase.json');
const creds = require('./config/accountCredentials.json');
// Normally config values are loaded from Cloud Runtime Config;
// here we'll stub functions.config() with our own testing values
configStub = sinon.stub(functions, 'config').returns({
firebase: {
credential: admin.credential.cert(serviceAccount),
databaseURL: firebaseConfig.databaseURL,
},
});
// Now we can require index.js and save the exports inside a namespace called myFunctions
myFunctions = require('../index');
// Now we initialize firebase to sign in and check database values below
firebase.initializeApp(firebaseConfig);
// Sign in and get auth token for use during tests
firebase.auth().signInWithEmailAndPassword(creds.email, creds.password).then(user => {
user.getToken().then(token => {
authToken = token;
done();
});
});
});
after(() => {
// Restore our stubs to the original methods
configStub.restore();
});
it('tests', done => {
const req = {
// <ADD QUERY OBJECT>
headers: { origin: '*' }, // Needed for cors middleware
};
const res = {
status (code) {
assert.equal(code, 200);
return this;
},
json (json) {
console.log(json);
// <ADD CODE TO CHECK VALUES WRITTEN TO DATABASE PROPERLY>
done();
},
setHeader () {}, // Needed for cors middleware
}
// <ADD FUNCTION CALL TO TEST>
// EXAMPLE: myFunctions.myFunction(req, res);
// http-triggered functions all end with res.status(CODE).json(JSON);
});
});
@algera
Copy link

algera commented Apr 5, 2018

FYI getHeader is now required as well

e.g.

      const res = {
        status (code) {
          assert.equal(code, 200);
          return this;
        },
        json (json) {
          console.log(json);
          // <ADD CODE TO CHECK VALUES WRITTEN TO DATABASE PROPERLY>          
          done();
        },
        setHeader () {}, // Needed for cors middleware
        getHeader () {}, // Needed for cors middleware
      }

@jQrgen
Copy link

jQrgen commented Apr 7, 2020

is the stub functions.configstill relevant?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment