Use mockgen to generate mock implementations by defining your target interface in Go code and running the tool with the interface name and destination package as arguments. The generated file provides a fully functional mock struct that satisfies the interface, allowing you to inject dependencies and control return values in your unit tests.
You can run mockgen directly from the command line or use the go generate directive for automation. For a simple interface like DataStore, you would first define the interface in your source file:
// datastore.go
package storage
type DataStore interface {
Get(key string) (string, error)
Save(key, value string) error
}
To generate the mock, run the following command in your terminal, ensuring you are in the module root:
mockgen -source=datastore.go -destination=datastore_mock.go -package=storage
This creates a datastore_mock.go file containing a MockDataStore struct and a MockDataStoreController. You can then use this mock in your tests to simulate behavior without hitting a real database:
// datastore_test.go
package storage_test
import (
"testing"
"github.com/golang/mock/gomock"
"your/module/storage"
)
func TestGet(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockStore := storage.NewMockDataStore(ctrl)
// Set expectations
mockStore.EXPECT().Get("user:1").Return("John Doe", nil)
// Execute logic under test
val, err := mockStore.Get("user:1")
if err != nil || val != "John Doe" {
t.Fatalf("expected 'John Doe', got %v", val)
}
}
For a more modern workflow, add a go:generate comment to your source file to automate this during development:
//go:generate mockgen -source=datastore.go -destination=datastore_mock.go -package=storage
Running go generate ./... will then create or update the mock file automatically. This approach keeps your test setup clean and ensures mocks stay in sync with interface changes. Remember to install the tool first via go install github.com/golang/mock/mockgen@latest if it isn't already in your $GOPATH/bin.