Integration tests for this blog

Published: 08 Feb 25 11:44 UTC

Last Updated: 08 Feb 25 11:46 UTC

Breaking with tradition to write a technical post.

I've been developing the blog functionality of this website for a few weeks now.

One of the challenges I encountered was to write a series of decent "integration" tests.

I've structured my application with MVC, so I needed to ensure the database logic (models) were interacting correctly with the controller and rendering the correct items in the view.

I have written this entire application in Golang. Two key tools I found incredibly useful were:

mockery

Mockery is an amazing tool that lets you stub entire components of your application, provided they are defined as interfaces and not structs.

In my use case this is very useful for mocking errors being returned by the database to test out the error handling code.

E.g. I define the following in .mockery.yaml (the mockery configuration file)

 1quiet: false
 2with-expecter: true
 3disable-version-string: true
 4all: true
 5mockname: "Mock{{.InterfaceName}}"
 6filename: "{{.InterfaceNameSnake}}.go"
 7keeptree: false
 8packages:
 9  github.com/fugu-chop/blah/blah/blah:
10    config:
11      dir: "./test/pkg/modeltest"
12      outpkg: "modeltest"
13    interfaces:
14      # PostService is my db/model logic for blog posts
15      PostService:

I run mockery from the CLI, and this generates typed code that mocks the response of the PostService.

I can then simulate error responses in my integration tests:

 1func TestPublish_PostServiceCreate_Error(t *testing.T) {
 2	postService := modeltest.NewMockPostService(t)
 3        // this EXPECT() method both asserts that the `Create` method will be called
 4        // AND specifies the behaviour to occur when `Create` is called
 5	postService.EXPECT().Create(mock.Anything).Return(errors.New("something went wrong"))
 6	mdParser := goldmark.New()
 7	c := controllers.NewPostsController(postService)
 8
 9        // Rest of test
10}

dockertest

Mockery is most useful for stubbing out components for error scenarios.

However, the majority of happy paths involve some testing of the database - e.g. that a record is written to the database on a Create method call.

Enter dockertest.

This package allows you to spin up a docker container containing a database engine of your choice (I use Postgres). It allows you to establish the connection, run your tests, and it cleans up after itself.

The documentation is very well written. The only issues I had were idiosyncrasies of my personal machine and implementation. Specifically:

Both of these tools were very useful in giving me good confidence in testing out the blog.

Useful Readings

Back