An Ode to mockgen: Because Writing Unit Tests Can Be Less Painful

Leonardo
2 min read1 hour ago

--

In the world of Go programming, unit testing can often feel like a chore, especially when it comes to creating the necessary mock objects. However, mockgen, a part of the GoMock library, offers a streamlined way to generate these mocks, simplifying the test writing process significantly. Let’s break down the essentials of using mockgen, complete with a practical example.

Installing Mockgen

Before getting into mock generation, you need to install mockgen. It’s part of the broader GoMock library and can be installed using Go’s package manager. Run the following command:

go get github.com/golang/mock/mockgen

Ensure that your GOPATH is correctly set, as mockgen will be placed in the $GOPATH/bin directory. Adding this directory to your system’s PATH allows you to run mockgen from any terminal.

Generating a Mock with Mockgen

The mockgen functions in two primary modes: reflect and source. Here, we focus on source mode, which reads Go source files to produce mock implementations.

Example: A Practical Go Module

Let’s assume you have a Go file that defines an interface for managing user profiles. Here’s a simple implementation of such a module:

// FileName: user.go
package user

// UserProfile defines the methods to manage a user's profile
type UserProfile interface {
UpdateName(userID int, newName string) error
FetchName(userID int) (string, error)
}

type UserManager struct{}

func (u *UserManager) UpdateName(userID int, newName string) error {
// Imagine this method interacts with a database
return nil
}

func (u *UserManager) FetchName(userID int) (string, error) {
// Imagine fetching the name from a database
return "John Doe", nil
}

Generating Mocks from the User Module

Now, to generate a mock for the UserProfile interface using mockgen, run:

mockgen -source=path/to/package/user.go -destination=path/to/mocks/user_mock.go

Flags Explained

- source: Path to the Go source file.
- destination: Path and filename where the mock file should be saved.
- package: (Optional) Specify the package name of the generated mock file.

Using the Generated Mocks in Unit Tests

With your mocks ready, it’s time to incorporate them into unit tests:

1. Import the mock package along with the testing package:

import (
"path/to/mocks"
"testing"
"github.com/golang/mock/gomock"
)

2. Write your test using the mock:

func TestUpdateName(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()

mockUserManager := mocks.NewMockUserProfile(mockCtrl)
mockUserManager.EXPECT().UpdateName(1, "Jane Doe").Return(nil)

// Insert test logic to interact with mockUserManager
}

In this example, the gomock.Controller orchestrates the lifecycle of the mock objects, and the EXPECT() method sets up what we anticipate our mock to receive.

Wrapping Up

The tool mockgen provides a powerful way for Go developers to generate and manage mock objects for unit testing efficiently. By automating the generation of mocks, it allows developers to focus more on the logic of their tests rather than the boilerplate of setting up mocks. Give mockgen a try in your next Go project and experience firsthand how it can simplify your testing strategy.

--

--

Leonardo

Software developer, former civil engineer. Musician. Free thinker. Writer.