PostgreSQL tests with Go and Docker | Brad

Leverage the Go highly effective STL, Docker, and SQL transactions to execute parallel exams for a PostgreSQL repository

A gopher using a stick to poke a PostgreSQL elephant loaded in a Docker dolphin.

Testing utilizing actual know-how as a substitute of mocks was not simple earlier than we had containers. For databases, normally, there was just one database server per machine and just one database per unit of utility.

Mocking is the commonly accepted resolution for testing database interplay. Mocks will help with edge circumstances like dropping a connection mid execution, however would you relatively take a look at that or take a look at your queries and guarantee they’re working as anticipated with an actual database. You may simply begin testing towards actual databases utilizing Docker.

As issues stand in 2022 and contemplating the out there instruments, mocking the database looks like testing Go code by writing a Go interpreter.

I share the identical views with Bill Kennedy with reference to testing methodologies and couldn’t have mentioned it higher myself. I deal with each bundle as an unit of code and in the case of testing an unit of code in my initiatives, my largest concern is making certain that it really works in manufacturing.

Following the thread from this tweet, you’ll find a response that serves as a catalyst for this text and the repositories carried out.


  • validate queries; no surprises in manufacturing.
  • establish misusages
  • compose complicated situations; guarantee your constraints are working as anticipated.


  • excessive price of managing a database lifecycle. Solved on this article 🙂

What instruments are essential?

Earlier than diving into the code I’m assuming that you’re already accustomed to Go and its highly effective normal library. The code situated in gists

Right here is an example repository the place you’ll find and run the exams offered on this article.

I’ll begin by presenting the result of the exams, then I’ll run you thru the setup wanted to execute the exams and I’ll find yourself with the exams implementation.


console output of go tests finishing in 4 seconds
take a look at output printed to console

The exams discovered within the ./internal/psql bundle are all executed, in parallel, towards an actual PostgreSQL database. The primary takeaway from right here is the execution time, sitting at ~4 seconds. The execution time contains beginning and destroying a recent PostgreSQL database, programmatically, with go.


Earlier than operating the bundle exams a setup for the PostgreSQL database have to be carried out. That is achieved with the assistance of TestMain perform and the next exterior packages: psqldocker +psqltest .

TestMain permits the developer to run arbitrary code earlier than and after operating the bundle exams.

I developed psqldocker to programmatically handle the lifecycle of PostgreSQL Docker containers.

With psqldocker.NewContainer() a brand new PostgreSQL Docker container is created. The container is stopped within the, which is executed after operating the bundle exams with m.Run() .

I additionally developed psqltest, a set of PostgreSQL testing utilities much like what/net/http/httptest is for net/http. The psqltest.Register() perform is a wrapper over DATA-DOG/go-txdb/db.go:Register() which registers a brand new SQL driver that when opening a database connection utilizing it, will begin that connection in an remoted SQL transaction.

Since each take a look at opens a brand new database connection in a separate SQL transaction, parallel take a look at execution is protected. This permits the developer to work with the identical database entity throughout a number of exams, for instance, the identical Person entity can be utilized for a number of exams that may alter its state.

With psqltest.NewTransactionTestingDB() a brand new database connection is created utilizing the driving force beforehand registered in TestMain with psqltest.Register(). The DSN(second enter parameter) offered to sql.Open() is the take a look at identify, it acts as an identifier for the underlying SQL transaction. Utilizing the identical DSN, the developer can open a number of database connections to the identical transaction. For instance, the identifier for the transaction within the first take a look at is TestUserRepository/CreateUser/Success.

The psqltest.NewTransactionTestingDB() implementation:

There you go, on this article, I confirmed you how one can programmatically ramp up and teardown a PostgreSQL database utilizing Docker.

I additionally carried out protected parallel exams to be executed towards the database occasion by opening the database connections in separate SQL transactions.

More Posts