Sunday, April 28, 2024
HomeGolangHow To Containerize Golang Unit and Integration Exams

How To Containerize Golang Unit and Integration Exams


This text is the fifth and remaining in a sequence masking all of the elements of implementing a contemporary REST API microservice step-by-step:

  1. Defining a SQL first knowledge mannequin with sqlc
  2. Implementing the REST API with Gin
  3. Configuring with Viper
  4. Constructing and operating in a container
  5. Containerized checks

All of the code for the sequence is out there right here.

Now that we now have constructed our API microservice, we wish to implement checks to make sure it’s working appropriately. We’ve a two-layered service design: the database layer and the HTTP API on high of it. So how are we going to check it?

We may determine to go full unit testing and implement unit checks for our database layer by testing every SQL question we now have generated and ensuring it behaves as anticipated by mocking the precise database. Then, we’d check the HTTP API by mocking the database layer and testing every API handler. This can be a frequent method and makes lots of sense.

One other method could be to do integration checks. The concept of integration checks is to check your utility solely utilizing its public APIs. So in our case, we’d:

  1. Begin the database and the microservice, precisely just like the manufacturing stack within the earlier article,
  2. Then we’d implement a REST API check shopper known as the microservice API to check all of the offered strategies.

That is additionally generally used within the trade to check a microservice-based structure and make sure the entire utility or its subsystems behave as anticipated.

Nevertheless, each approaches current some challenges. On the one hand, going full-on unit testing requires writing lots of check code, and in our case, testing the database layer is testing the Postgres SQL driver and sqlc generated code. In the identical spirit, testing the HTTP layer independently, requiring mocking the database layer, is lots of code that should be maintained.

Alternatively, integration checks which solely depend on APIs are large however the checks we will implement are restricted to what’s publicly uncovered by the API. We don’t wish to implement a non-public API for testing functions!

Better of Each Worlds?

So, on this article, we’ll take the very best of each worlds and implement one thing in-between unit and integration checks:

  • To keep away from mocking the database, we’ll begin a containerized database to help our checks,
  • We won’t decouple the shopper and the server to allow fine-grained checks however bypass the community layer and carry out requests straight on the server.

Please observe that this can be a very opinionated method. It is vitally environment friendly and will certainly prevent lots of time.

To write down our checks, we’ll use the stretchr/testify library to group our checks beneath check suites. Utilizing suites permits us to carry out initialization steps earlier than the entire suite and earlier than every check:

package deal authors

// ...

kind ServiceTestSuite struct {
	suite.Suite
	router  *gin.Engine
	queries *database.Queries
}

// To ensure that 'go check' to run this suite, we have to create
// a standard check operate and go our suite to suite.Run
func TestServiceTestSuite(t *testing.T) {
	suite.Run(t, new(ServiceTestSuite))
}

func (suite *ServiceTestSuite) SetupSuite() {
	cfg, err := config.Learn()
	suite.Require().NoError(err)

	postgres, err := database.NewPostgres(cfg.Postgres.Host, cfg.Postgres.Person, cfg.Postgres.Password)
	suite.Require().NoError(err)

	suite.queries = database.New(postgres.DB)
	service := NewService(suite.queries)

	suite.router = gin.Default()
	service.RegisterHandlers(suite.router)
}

func (suite *ServiceTestSuite) SetupTest() {
	suite.queries.TruncateAuthor(context.Background())
}

The SetupSuite methodology is executed as soon as earlier than the execution of the entire suite. We arrange the server the identical method we do for the principle operate. The one distinction right here is that we don’t begin the server. Every thing else is an identical: we use the identical configuration mechanism, we instantiate the database connection in the identical method, and we register the identical handlers.

The SetupTest methodology is executed earlier than each check of the suite. In our case, we truncate the writer database to begin with a clear slate.

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments