Let’s keep it simple: integration tests shouldn’t be a hassle. You want to test your Go app against real services—without the headache of managing external dependencies. That’s where Test containers steps in: spinning up real, throwaway services like databases right within your test suite. Super clean, super repeatable.
Why This Matters
Mocking dependencies is fast, but it can miss real-world issues. On the flip side, managing test environments is a pain—hard to keep consistent and expensive to set up. Testcontainers lets you run real services (e.g., Cosmos DB emulator) in Docker, inside your tests, and tear them down afterward. It’s like testing in production conditions… but safe.
Testcontainers Goes Native in Go
Testcontainers for Go (testcontainers-go) gives you an idiomatic Go API to control Docker containers right from your tests. It handles everything—container set up, ports, health checks, lifecycle management—so you don’t have to write boilerplate.
Real-World Example: Cosmos DB Emulator
The tutorial walks you through using testcontainers-go with the Azure Cosmos DB emulator:
- Choose a flavor: They use the Linux-based emulator (works with ARM64 setups), but you could use other versions too.
- Test flow overview:
- Spin up the emulator in Docker
- Run your Go integration tests against it
- Automatically shut it down afterward
- Spin up the emulator in Docker
This means every test starts clean, gives real behavior feedback, and leaves no mess behind.
Better Structure: Setup, Test, Cleanup
Instead of launching containers per test, use Go’s TestMain to set up the emulator once for the suite, then run multiple tests against it. Afterward, tear it down—efficient and tidy.
Here’s the gist:
- TestMain boots the emulator container
- Initializes your client (e.g., connecting via SDK)
- Seeds test data (prep for test cases)
- Runs the tests
- Cleans up the container afterward
Smart Container Setup
They define everything in a ContainerRequest:
- Use the emulator image
- Expose ports (e.g., 8081)
- Define readiness checks (wait until listening)
- Set environment variables (disable explorer, use HTTPS)
This ensures the container only kicks off tests when it’s fully ready. Clean and reliable.
Smooth Connection & Cleanup
They also show how to connect to the emulator—using a client with custom TLS transport so it trusts the self-signed certificate (only in test/dev). After the tests wrap up, the container is terminated to avoid leaks.
Why It All Matters
Using Testcontainers in Go gives you fast, reliable, and realistic integration tests. You can expand beyond Cosmos to anything with a Docker image—like Postgres, Kafka, etc. As long as it’s containerized, your tests become easier, safer, and more trustworthy.
TL;DR — Bottom Line
Stop juggling test environments. Use testcontainers-go to spin up real services in Docker automatically, test against them, and tear down when you’re done. It’s clean, dependable, and production-near testing with none of the setup headache.