google-cloud-go
google-cloud-go copied to clipboard
firestore: Provide function to configure emulator
Is your feature request related to a problem? Please describe. I'm writing unit tests to exercise code which connects to Firestore. What would be really nice is to have an in-process mock for testing. However, barring that, it's sufficient to run the Firestore emulator as a subprocess, and connect to it from unit tests.
However, the only officially supported way to connect to an emulator is to set the FIRESTORE_EMULATOR_HOST
environment variable. Even if I were to do something like os.Setenv("FIRESTORE_EMULATOR_HOST", ...)
, that would mean that I couldn't run tests in parallel with different emulators, as the environment variable is global.
What I've resorted to instead is to adapt the logic that is used internally here:
https://github.com/googleapis/google-cloud-go/blob/096c584342beb49d9653a670d7813b9dbaca72b8/firestore/client.go#L64-L71
and here:
https://github.com/googleapis/google-cloud-go/blob/096c584342beb49d9653a670d7813b9dbaca72b8/firestore/client.go#L335-L346
Describe the solution you'd like
I would like there to be a first-class API for creating a *firestore.Client
which accepts an emulator address as an argument rather than by consulting FIRESTORE_EMULATOR_HOST
.
Thanks for filing the issue and for your clear description!
I know the FIRESTORE_EMULATOR_HOST
approach is used across the language clients for firestore. @BenWhitehead is an owner for the firestore clients so I'm asking him to chime in on whether adding an API for this as well would be feasible.
Emulator boostrapping and lifecycle management is something that has recently come up for several languages and as such is going to be larger than any one client to be improved. I'll include this request in the discussion around the improvements.
Related issues:
- https://github.com/googleapis/java-firestore/issues/190
- https://github.com/googleapis/java-firestore/issues/210
- https://github.com/firebase/firebase-admin-node/issues/776
Even if I were to do something like
os.Setenv("FIRESTORE_EMULATOR_HOST", ...)
, that would mean that I couldn't run tests in parallel with different emulators, as the environment variable is global.
For what it's worth, the emulator is a reasonably heavyweight and slow-starting Java process, I wouldn't want to run multiple, nor would I want to start a new one per test.
Since the Firestore emulator accepts any project id and doesn't require authentication, I have a helper that picks a random project id (prefixed with the test name, for debugging), and clears the data for each project id before the test. It works great with parallel tests, subtests, etc.
This is a reasonable point, have you considered using unique project ids per test (or per parallel group)?
I'm no longer working on this project, but I don't see why that approach wouldn't work (maybe with the modification that, instead of random project IDs, you use an atomic counter to guarantee uniqueness).
@joshlf In my case, the tests run in multiple subprocesses, and I didn't want to impose coordination. The project id used concatenates a prefix, name of current test, and a 64-bit random number. It's realistically never going to collide.
If you look at the Firestore tests, you'll see that we use a mockServer
that creates a gRPC interceptor for emulating service responses. If the emulator is too-heavyweight for you, you might consider a similar approach.
Hi, I want to write a test using testcontainers-go and as you can see here java client already allows to set the host and port, which is a random port provided by testcontainers. Can we reconsider it and make it available in go client, please?