Uri is a Firebase Expert based in Tel Aviv, Israel. He works at WatchDox, organizes the Tel Aviv Google Developers Group, and is an avid Angular fan.

I built an open-source project called firebase-server to implement end-to-end tests in my own application. With firebase-server, my end-to-end tests are now running 40% faster and I no longer depend on an Internet connection for running the tests in development.

Testing With Firebase

Because Firebase is a cloud service, it poses some challenges for performing automated tests. For unit tests, using a mock for the Firebase client library will work well. If you are writing a web application, you can quickly mock just the methods you use with either Sinon or Jasmine, or use MockFirebase, an open-source Firebase mock.

When it comes to writing end-to-end tests, however, you usually want to test the system as a whole, including the integration with the real Firebase client library to verify that the realtime synchronization between clients is functioning correctly. In addition, the end-to-end testing code runs outside the context of your application and you should make some assertions about the data it saves to Firebase.

Before building firebase-server, I used the Firebase client library in my end-to-end tests to talk directly to the Firebase cloud service. The issues with this method were that I needed an internet connection to run the tests and my tests ran slowly if my internet connection was lagging.

Running a Local Firebase Server

Frustrated with my end-to-end tests occasionally timing out, I started looking for a solution. MockFirebase would solve the problem only if my testing and app code lived within the same process, and even then, I would not be testing the real Firebase client library.

I decided that the best solution would be to put MockFirebase into a separate process, and make the Firebase client library connect to that process. This is when firebase-server was born!

firebase-server is a simple Node module which speaks the Firebase Wire Protocol, and can be used as a proper substitute for the real Firebase server in your e2e testing scenarios. You can also use it to develop code against Firebase in times when you don't have an internet connection.

Before you can connect to your Firebase, there is one limitation of the client library we need to work around: it requires the hostname of your firebase to include exactly two dots. You can work around this by adding a hosts file entry pointing 'test.firebase.localhost' to the local IP 127.0.0.1.

Now, everything is ready and you can switch to your local Firebase server. Simply change the connection string from https://myFirebase.firebaseio.com to ws://test.firebase.localhost:5000. For instance:

If you do not wish to edit your hosts file, you can also use ws://127.0.1:5000. This trick seems to work inside Chrome and Firefox. With Node.JS, you can use another trick: overriding the constructor of the faye-websocket Client. Check out the firebase-server unit testing code for an example.

I'd like to hear what you think!

I'd love to hear any suggestions you have on firebase-server. You can file an issue or submit a pull request on GitHub, or send me your feedback on Twitter, I'm @UriShaked.

I thought that was intentional. The article notes that the Firebase client library requires a hostname with exactly two dots. A 3-part IP address is obviously not standards-compliant, but apparently it works in some browsers. Or at least that's how I interpreted it (I haven't tried it).

Hi Uri, thanks for this much useful tool! I find it rather limiting that the Firebase API does not provide a callback or event to notify the client when the server has correctly (or not) acknowledged its request. This makes end to end testing rather complicated. I haven't found a way to perform integration testing from the client. I guess with your tool I could have the two processes communicate and perform testing. But I was wondering if you have found a better way to test whether, for instance, the events sent to Firebase Analytics are being recorded. Have you found a way to do this strictly from the client? Thanks a lot!