
When testing locally, your application is likely to make use of services like databases or messaging. In later chapters, as these services are introduced, I will explain the options for using or emulating them in your local loop. However, here are the high-level options.
Actual Service Instance
Using a real service for integration testing keeps to the 12-factor principle of dev/prod parity. Many services have the option to run at minimal capacity for testing. If you are working locally, there is the issue of network lag; however, if you are using one of the in-cloud options (Cloud Shell Editor or Cloud Workstations), this can work very well.
Local Emulator
Sometimes, it just may not be cost-effective or possible to use a genuine service for integration testing. An example is the Cloud Spanner database, which used to have a high minimal cost deployment, although the introduction of fractional deployments has mitigated this. However, another is not having an internet connection. For example, suppose you are developing on an airplane or on a cruise ship (as I did once). In this case, a local emulator is a good option.
Here are some examples of emulators of Google services used in this book:
Cloud Pub/Sub
The Pub/Sub emulator provides an in-memory implementation of the API for local testing purposes.
Cloud Firestore
The Firestore emulator is part of the Firebase Local Emulator Suite, which lets you run Firestore, Realtime Database, Firebase Authentication, Cloud Functions, and Cloud Pub/Sub locally.
Cloud Spanner
The Cloud Spanner emulator provides a local, in-memory environment for development and testing.
Cloud Storage
While not an emulator in the traditional sense, the gsutil tool can interact with the local file system in a way that emulates interaction with the Cloud Storage API.
Note that local emulators may not offer complete functionality or may behave differently than the actual services in some cases. Therefore, it’s crucial to test your application in the actual Google Cloud environment before deploying it to production.
Local Container
In scenarios where official emulators are unavailable or access to the actual service is restricted, leveraging local containers can provide a robust alternative. One of the projects that facilitate this is the Testcontainers project.
Testcontainers is a highly regarded Java library specifically designed for facilitating the use of Docker containers within automated testing environments. Its central purpose is to allow you to emulate various services in isolated, short-lived containers, ensuring your tests run against a fresh instance of the service every time. This attribute makes it an effective tool for improving the reproducibility and reliability of your automated testing pipeline.
The library is known for its extensive coverage, providing disposable containers for a broad range of services such as databases, web browsers (with Selenium), message queues, and more. It enables developers to execute integration tests against a wide variety of systems without needing to install them locally or on a shared test server.
In addition to its existing functionalities, Testcontainers has an active community contributing to its continuous improvement and expansion. New disposable containers mimicking different services are frequently added, further widening the spectrum of test scenarios it supports.
However, while local containers and emulators like those from Testcontainers can offer substantial benefits for local development and testing, they may not perfectly mirror the behavior of live services. Therefore, it’s always important to run final validation tests on the actual production-like services whenever possible, ensuring that your application behaves as expected under real-world conditions.