Testing Cosmos DB writes locally and in GitHub Actions with the emulator
The Azure Cosmos DB blog shows how to test a database-backed feature against the Azure Cosmos DB Emulator running in Docker, then run the same tests in GitHub Actions. The example is a Python demo app, but the pattern applies to any .NET service that talks to Cosmos DB. Each pull request update runs against a fresh emulator, so you can check that a write reached storage and changed the answer, not just that the HTTP call returned 200.
Key points
- Run the emulator from the vNext image in Docker, bound to 127.0.0.1, and wait on the /ready endpoint before seeding data.
- An HTTP 200 response does not prove a write; assert that the record reached the database and that the next answer changed.
- The scripts.ci helper starts an isolated emulator container per run and passes its randomly chosen endpoint to the tests.
- Each database test gets its own seeded database, and cleanup removes the container even after a handled failure.
- The GitHub Actions workflow runs on pull_request opened, synchronize and reopened events and cancels superseded runs.
- The emulator does not enforce authentication, so keep its ports on loopback and never point it at production data.
The post shows how to confirm that a change to a database-backed feature really works, instead of trusting a successful HTTP response. The author uses the Azure Cosmos DB Emulator in Docker to check three things: the write reached storage, the application read the updated record, and the next answer reflects the change. The demo app, FleetCharge, is a Python project built with Microsoft Agent Framework and FastAPI, and it runs the Phi-3.5 model locally through Ollama.
The local setup pulls the vNext emulator image, binds its ports to loopback and seeds sample data before starting the API. A helper script then handles CI: it starts an isolated emulator container on free ports, waits for its readiness endpoint, and runs linting, type checks and component tests. A GitHub Actions workflow runs these checks on each pull request update, plus a separate job for the live model. Because the emulator does not enforce authentication, the setup is for testing only.
Real-world use
- Testing an ASP.NET Core or minimal API service that writes to Cosmos DB and must return the updated data on the next request.
- Adding a CI gate that runs database tests against a fresh emulator on every pull request update.
- Running a local development and test loop against Docker without needing an Azure account or cloud credentials.
Why it matters
For Cosmos DB features, a 200 response does not prove the data was stored or read back, so tests should check the database and the next answer. Using the same emulator locally and in CI gives you production-like confidence before a pull request merges.
Related stories
- .NET 8 and 9 End of Support: A Deployment-First Migration ChecklistDEV Community: #dotnet2 d ago
- Metalama 2027.0 adds interceptors to redirect method calls at build timeMetalama / PostSharp Blog4 d ago
- Writing executable specifications with Bobcat in C#Jeremy D. Miller (The Shade Tree Developer)5 d ago