Couchbase Integration Testing for Golang via Testcontainers

Integrate Couchbase with Golang via Singleton Pattern and Test Driven Development approach

Mustafa Onur Aydın
Trendyol Tech
4 min readDec 21, 2020

--

In Trendyol, we are developing microservice projects with different programming languages and technologies. The Golang is one of them. We are following test driven development approach to development process. Because of that, we are focusing to apply test driven development approach when we are learning a new programming language. Test driven development is the only first step. We are following SOLID principles, caring readable, maintainable clean code and architecture, apply design patterns, four key metrics, and more :) If you are interested too these approach like us, you can be a part of the team. You can see available roles click over here. Join us!

Why we need integration tests?

The first step of applying test driven development is unit test. However, in some cases, unit tests are not enough. In some cases, you need to write component tests for understanding your units working together right. What if we are dependent on some third-party unit or a system like database, messaging queues etc. In these cases, integration testing will helps. You can simulate cases the same as production.

Testcontainers is the known solution for writing integration tests. You can start easily your third party dependent platforms as a docker container. But there is no preconfigured couchbase implementation in the current testcontainers golang solution.

Couchbase Integration Test for Golang

Testcontainers is allowing to run any docker image. In the official couchbase docker image is not configured via docker environment variables. You can initialize via user interface or command-line interface which is provided from couchbase. A configurable couchbase docker image with environment variable will be so useful when writing integration tests with testcontainers. For that reason, I’m going to use my customized couchbase docker image which can initialize via environment variables.
This image is open source and you can access it here over github. And also the image is using over dotnet-testcontainers pre-configured Couchbase solution which is contributed from me.

You can pull the image over docker hub like the following;

docker pull docker.io/trendyoltech/couchbase-testcontainer:6.5.1

Default values of environment variables are following;

You can override environment variables for customizing. Here is an example of couchbase integration test over golang via testcontainers;

In the above example, testcontainers generic container is starting Couchbase over Golang background context with customized environment variables. After that, you need to defer terminating of container. This will guarantee for you to destroy container after test. In this example, test expecting and implementation that returns Couchbase’s Cluster object. After that test can assert is Couchbase created with the expected configuration and bucket.

In my Couchbase docker image, you can see “couchbase-dev started” log if everything is fine.

wait.ForLog("couchbase-dev started").WithStartupTimeout(45 * time.Second)

Please be sure that you have enough resources for running Couchbase container which should be a minimum that is defined over docker image environment. Otherwise, container will not start and the test will fail after the startup timeout which you defined as above.

Test driven development approach steps are following the picture. Now the fail test is ready. Let’s write code and be sure that will be working on production fine.

Integrate Couchbase for Golang

Let’s check first how we can connect Couchbase and open bucket. Here is an example from Couchbase documentation.

func main() {
cluster, err := gocb.Connect("localhost", gocb.ClusterOptions{
Username: "User",
Password: "password",
})
if err != nil {
panic(err)
}
}

This is the first information we need. Now, this is the right time to consider that how the function will create cluster only one time. Right answer is “Singleton Pattern” but how? Golang provides “Once” object which is under sync package and Once is an object that will perform exactly one action. No need to worry about race conditions! The solution is following;

In the above code, we are creating a cluster like Couchbase’s documentation advice. “Once” is provides that the code block runs only one time. In the first call, this function creates a cluster and assigns over the global variable. After that function returns the same cluster in every call.

This is a sample application. You can make connection variables as an environment variable and you can override over on test. You may need to consider edge and boundary cases depending on your solution requirements like timeout etc.

You can access the sample project from the following gitlab repository;
https://gitlab.com/golang-testcontainers/integration-testing-couchbase-for-golang

Conclusion

This article will help to understand writing integration tests with test driven development approach for golang via testcontainers. You can write any integration test for any depend platform via following steps in this article. Testcontainers are useful for end-to-end tests too.

You can run your tests over pipeline like Gitlab pipeline. You can define a blocker step before deployment when tests fail. Because of that no one can destroy your solution accidentally. Tests are written in once but runs unlimited. This will helps you sleep more comfortable at night :)

Thanks for reading this article! Do not hesitate to make criticism with comments.

--

--