38
votes

Is there a way to run firestore locally (e.g. for testing purposes)?

What would the approach to write tests against the DB (except of using mocks)

7

7 Answers

22
votes

Update 2020:

There's now also a Firebase Emulator Suite.

Update Nov 2018:

Local emulation, at least for the purpose of testing Firestore rules, was demoed at Firebase Summit 2018 using @firestore/testing and documented under Test your Cloud Firestore Security Rules.

It looks like it's along the lines of:

const firebase = require(`@firebase/testing`)
const app = firebase.initializeTestApp({
  projectId: 'my-project',
  auth: { uid: '123', email: '[email protected]' }
})

const attempt = app.firestore()
  .collection('colId').doc('docId').get()
firebase.assertFails(attempt)
firebase.assertSucceeds(attempt)

It seems early-on, as it's not been noted in the release-notes, but I'm sure it's coming along.

19
votes

There is not currently, but stay tuned as it's something we want to provide.

In the meantime we suggest uses a separate testing project to cover this. The daily free tier per project helps with this too.

8
votes

You can run the Firestore emulator by running:

gcloud beta emulators firestore start

and then set the FIRESTORE_EMULATOR_HOST environment variable as per the console output (e.g. run export FIRESTORE_EMULATOR_HOST=::1:8505).

This requires the Google Cloud SDK and a Java 8+ JRE installed and on your system PATH.

2
votes

for a firestore testing write a js example test.js you could test write with this format example

var data = {
        value: {createTime: new Date(),
                updateTime: new Date(),
                fields:{

                        name:{stringValue:'new value data'},
                        age:{integerValue:50}
                      }
        },
        oldValue: {createTime: new Date(),  //old create time
                updateTime: new Date(),  //old update time time
                fields:{

                        name:{stringValue:'olvalue data'},
                        age:{integerValue:50}
                      }
        }
      };
testFireStoreEvent(data);

for run execute

firebase experimental:functions:shell < test.js

UPDATE!!!! VALID FOR WRITE AND UPDATE EVENTS

var data = {
    before: {  
          //your before data

    },
    after: {

        //your after data
     }
  };
testFireStoreEvent(data);
1
votes

There are two libraries which attempt to facilitate mocking of the firebase sdk.

1) https://github.com/soumak77/firebase-mock
2) https://github.com/mikkopaderes/mock-cloud-firestore

I currently use the first one, since it seems to have a bit more of the SDK implemented.

They're not perfect, but they're currently sufficient for my needs, and are preferable to the other approaches since they're entirely in-process.

Note that firebase-mock (#1) does cause a webpack error if used as-is from Webpack/web code. To resolve, you can use option #2 (mock-cloud-firestore), or use the workaround mentioned here (until a fix gets merged): https://github.com/soumak77/firebase-mock/issues/157#issuecomment-545387665

Other options:

3) Firestore emulator: needs the google-cloud-sdk, and relies on a separate process
4) Separate test project: relies on connection to the internet, which also means possible quota limitations/costs
5) firebase-server: Only supports the realtime-database api, not Firestore

1
votes

Firestore can be setup in local using gcloud.

Start the firestore emulator by running gcloud beta emulators firestore start --host-port=localhost:8081 and if it started successfully you will be seeing Dev App Server is now running

In case if you are using @google-cloud/firestore then create the Firestore instance in this way

// Firestore instance only for test env
const { Firestore } = require('@google-cloud/firestore')
const instance = new Firestore({ projectId; 'Your project id', host: 'localhost', 'port': 8081})
1
votes

Now you have an option to work with local firestore emulator by setting local host:

var db = firebaseApp.firestore();
if (location.hostname === "localhost") {
  db.settings({
    host: "localhost:8080",
    ssl: false
  });
}

https://firebase.google.com/docs/emulator-suite/connect_and_prototype#instrument_your_app_to_talk_to_the_emulators