Ben Hogan
Ben Hogan

Reputation: 65

Cannot call Firestore from Cloud Functions unit tests

Developing Google cloud functions locally. Trying to test functions that invoke Firestore. Here is a minimal example.

functions/index.js:

require ('dotenv').config();

const functions = require ('firebase-functions');
const admin = require ('firebase-admin');
admin.initializeApp();

exports.addMessage = functions.https.onRequest (async (req, res) => {
  const original = req.query.text;
  const writeResult = await admin.firestore().collection ('messages').add ({text: original});
  const docSnap = await writeResult.get();
  const writtenText = docSnap.get ('text');
  res.send (`Message with text: ${writtenText} added.`);
});

functions/test/index.test.js:

const admin = require ('firebase-admin');
const firebase_functions_test = require ('firebase-functions-test')({
  projectId: 'my-project-id'
}, '/path/to/google-application-credentials.json');
const testFunctions = require ('../index.js');

describe ('addMessage()', () => {
  it ('returns Message with text: Howdy added.', (done) => {
    const req = {query: {text: 'Howdy'} };
    const res = {
      send: (body) => {
        expect (body).toBe (`Message with text: Howdy added.`);
        done();
      }
    };
    testFunctions.addMessage (req, res);
  });
});

Starting jest from functions folder:

(Among other test-related output):

FAIL  test/index.test.js
  ● addMessage() › returns Message with text: Howdy added.

    TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type object

       7 | exports.addMessage = functions.https.onRequest (async (req, res) => {
       8 |   const original = req.query.text;
    >  9 |   const writeResult = await admin.firestore().collection ('messages').add ({text: original});
         |                                                                       ^
      10 |   const docSnap = await writeResult.get();
      11 |   const writtenText = docSnap.get ('text');
      12 |   res.send (`Message with text: ${writtenText} added.`);

      at GrpcClient.loadProto (node_modules/google-gax/src/grpc.ts:166:23)
      at new FirestoreClient (node_modules/@google-cloud/firestore/build/src/v1/firestore_client.js:118:38)
      at ClientPool.Firestore._clientPool.pool_1.ClientPool [as clientFactory] (node_modules/@google-cloud/firestore/build/src/index.js:326:26)
      at ClientPool.acquire (node_modules/@google-cloud/firestore/build/src/pool.js:87:35)
      at ClientPool.run (node_modules/@google-cloud/firestore/build/src/pool.js:164:29)
      at Firestore.request (node_modules/@google-cloud/firestore/build/src/index.js:983:33)
      at WriteBatch.commit_ (node_modules/@google-cloud/firestore/build/src/write-batch.js:496:48)
      Caused by: Error:
      at WriteBatch.commit (node_modules/@google-cloud/firestore/build/src/write-batch.js:415:23)
      at DocumentReference.create (node_modules/@google-cloud/firestore/build/src/reference.js:283:14)
      at CollectionReference.add (node_modules/@google-cloud/firestore/build/src/reference.js:2011:28)
      at Object.<anonymous>.exports.addMessage.functions.https.onRequest (index.js:9:71)
      at Object.addMessage (node_modules/firebase-functions/lib/providers/https.js:50:16)
      at Object.done (test/index.test.js:17:19)

Environment:

"node": "10"
"firebase-admin": "^8.12.1",
"firebase-functions": "^3.7.0"
"firebase-functions-test": "^0.2.1",
"jest": "^25.5.4"

Upvotes: 0

Views: 580

Answers (1)

Ben Hogan
Ben Hogan

Reputation: 65

Solved by adding jest.config.js to functions/:

module.exports = {
    testEnvironment: 'node'
};

Solution based on this (but NB I needed to place jest.config.js in functions/, not the project root).

Also tried this but appeared to do nothing.

Tests now run perfectly except that they end with a Jest error:

Jest did not exit one second after the test run has completed.

This usually means that there are asynchronous operations that weren't stopped in your tests. Consider running Jest with `--detectOpenHandles` to troubleshoot this issue.

This seems to be harmless.

Thanks @gso_gabriel for the valuable links!

Upvotes: 2

Related Questions