Testing with testify & mockery
Go's testing package is enough for correctness, but testify improves failure messages and mockery generates mock implementations from interfaces.
Search across all documentation pages
Go's testing package is enough for correctness, but testify improves failure messages and mockery generates mock implementations from interfaces.
Together they speed up table-driven tests, HTTP handler checks, and service-layer doubles without abandoning idiomatic Go interfaces.
Quick-reference recipe card - copy-paste ready.
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestSum(t *testing.T) {
require.Equal(t, 5, sum(2, 3))
}# mockery v2+ (install binary separately)
mockery --name=UserRepository --dir=./internal/user --output=./internal/user/mocksWhen to reach for this:
t.Fatalf noise hides the first diffhttptest servers and databasespackage user_test
import (
"context"
"errors"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"example.com/libdemo/internal/user"
)
type mockRepo struct{ mock.Mock }
func (m *mockRepo) FindByID(ctx context.Context, id string) (user.User, error) {
args := m.Called(ctx, id)
return args.Get(0).(user.User), args.Error(1)
}
func TestService_GetUser(t *testing.T) {
repo := new(mockRepo)
repo.On("FindByID", mock.Anything, "u1").Return(user.User{ID: "u1"}, nil)
svc := user.NewService(repo)
got, err := svc.GetUser(context.Background(), "u1")
require.NoError(t, err)
assert.Equal(t, "u1", got.ID)
repo.AssertExpectations(t)
}
func TestService_GetUser_NotFound(t *testing.T) {
repo := new(mockRepo)
repo.On("FindByID", mock.Anything, "missing").Return(user.User{}, errors.New("not found"))
svc := user.NewService(repo)
_, err := svc.GetUser(context.Background(), "missing")
require.Error(t, err)
}What this demonstrates:
require for fatal preconditions, assert for additional checks in the same testmock.Mock (mockery generates this shape)AssertExpectations verifies all expected calls happenedsuite.Suite for setup/teardown hooks on methods named TestX.On/Return helpers.| Helper | On failure | Use for |
|---|---|---|
require.* | Stops test | Setup, errors that invalidate rest of test |
assert.* | Marks failure, continues | Multiple independent field checks |
cmp.Diff (stdlib) | Manual | Complex structs when testify diff is noisy |
type UserRepository interface { ... } in production package.go generate with a //go:generate directive.//go:generate mockery --name=UserRepository --output=./mocks --outpkg=mocksmocks subpackages to avoid import cycles.context.Context through mocks the same way production code does.errors.Is / errors.As with testify ErrorIs.t.Parallel() or isolate state per test.go generate ./... in CI or pre-commit.mock.MatchedBy for partial matchers when needed._test.go files only.| Alternative | Use When | Don't Use When |
|---|---|---|
stdlib testing only | Zero-deps policy | Large teams want consistent diffs |
google/go-cmp | Deep struct compare | You want one assertion library |
gomock (go.uber.org/mock) | Recorder-style mocks preferred | Team already standardized on mockery |
| Hand-written fakes | Simple in-memory behavior | Call order verification is critical |
Yes for most application repos - the dependency is small and test-only; stdlib purists can stay on cmp and manual t.Helper.
Follow your org's pinned binary; both generate similar mocks - document the install path in CONTRIBUTING.
Either commit for reproducible CI or regenerate every test run - pick one policy and enforce in review.
That section covers httptest, benchmarks, and fuzzing; this page focuses on testify and mockery libraries specifically.
No - prefer table-driven functions for pure logic; suites help shared HTTP server setup.
Implement RoundTripper fakes or use httptest.Server instead of mocking http.Client internals.
Always run go test -race in CI; mocks do not remove shared-state races in production code.
No - follow Go's small interface rule; one or two methods per mock keeps tests readable.
Use buffer handlers or observer cores; testify asserts on parsed fields after the log call.
Support evolves with versions - generate from concrete interface instantiations your code actually uses.
Stack versions: This page was written for Go 1.26.x (Green Tea GC default, go fix modernizers - verify patch at build), chi (latest - verify at build), gin (latest - verify at build), echo (latest - verify at build), google.golang.org/grpc (latest - verify at build), sigs.k8s.io/controller-runtime (latest - verify at build), kubebuilder (latest - verify at build), tinygo (latest - verify board targets at build), wazero (latest - verify at build), and golangci-lint (latest - verify linter set at build).
Reviewed by Chris St. John·Last updated Jul 19, 2026