Unit and/or acceptance testing is as we all know, critical to application performance. So many applications use 3rd party services as their backend, but we still need to be able to run our test suites, without blowing out our billing, or slowing down our tests inordinately.
In a project I've been working on, we had end-to-end tests in which the application was spun up by a DI container, which initialised Firebase as part of its initialisation. Various endpoints in the application depended on the default Firebase app being initialised by the time that they were called, and would throw a ValueError with the message "The default Firebase app does not exist. Make sure to initialize the SDK by calling initialize_app()." if we just skipped Firebase initialisation. We had to figure out a way to convince the Python Firebase Admin SDK that it was initialised, without having to configure any legitimate Firebase credentials in our testing environment.
To initialise the Firebase Admin SDK, we use the firebase_admin.initialize_app
method. This method takes a credential object, which must be an instance of firebase_admin.credentials.Base
,
and an options dictionary. Looking at the
Firebase Admin SDK's own test suite,
it initialises the SDK by passing in a custom subclass of firebase_admin.credentials.Base
, which extends
it with the minimal possible configuration. From that file:
class MockCredential(firebase_admin.credentials.Base):
"""A mock Firebase credential implementation."""
def __init__(self):
self._g_credential = MockGoogleCredential()
def get_credential(self):
return self._g_credential
This simply overwrites the _g_credential instance variable with an instance of a new class, MockGoogleCredential
.
That class is defined just above this code as the following:
class MockGoogleCredential(credentials.Credentials):
"""A mock Google authentication credential."""
def refresh(self, request):
self.token = 'mock-token'
@property
def service_account_email(self):
return 'mock-email'
Now, we can initialise the Firebase Admin SDK in our app by running the following function:
def fake_firebase_init():
"""Fake the Firebase Admin SDK being set up."""
firebase_admin.initialize_app(MockCredential(), {"projectId": "mock-project-id"})
After running it, Firebase will think it's been successfully initialised, but won't be able to perform any authentication actions - perfect for our requirements.
That's all for today, until next time!
Alex