Mocks and Stubs — Specification¶
This page collects authoritative references for Go test-double tooling: package paths, versioning notes, key APIs, command-line flags, and the fork history that sometimes confuses newcomers (golang/mock is archived; the active fork is go.uber.org/mock). Nothing here is invented; every package listed is real and discoverable via go doc or its README.
Table of Contents¶
- Standard library —
testing github.com/stretchr/testify/mockgithub.com/vektra/mockerygo.uber.org/mock(formerlygithub.com/golang/mock)github.com/jarcoal/httpmocknet/http/httptestgithub.com/DATA-DOG/go-sqlmock- Fork history and lineage
- Compatibility matrix
Standard library — testing¶
The testing package itself does not provide a mock framework. It provides only:
*testing.Tfor assertions,t.Helper()for cleaner failure traces.t.Cleanup(func())(Go 1.14+) for deterministic teardown — useful to reset mock state.t.TempDir()for filesystem fakes.
Everything else — assert, mock, require — lives in third-party packages. This is intentional. Go's standard library treats test doubles as a style question, not a framework one.
Relevant doc anchors:
github.com/stretchr/testify/mock¶
Part of the testify suite. Provides a reflection-based mock object with expectation recording.
Core API:
type Mock struct { ... }
func (m *Mock) On(method string, arguments ...interface{}) *Call
func (m *Mock) Called(args ...interface{}) Arguments
func (m *Mock) AssertExpectations(t TestingT) bool
func (m *Mock) AssertCalled(t TestingT, method string, args ...interface{}) bool
func (m *Mock) AssertNumberOfCalls(t TestingT, method string, n int) bool
The Call returned by On supports chaining:
.Return(values...)— what the mock returns..Times(n)— exact call count..Once(),.Twice()— sugar forTimes(1),Times(2)..Run(func(args mock.Arguments))— side-effect closure invoked on call..Maybe()— optional call, does not failAssertExpectationsif not invoked..NotBefore(other *Call)— basic ordering constraint.
Argument matchers:
mock.Anything— wildcard.mock.AnythingOfType("string")— typed wildcard.mock.MatchedBy(func(x T) bool { ... })— predicate.
Caveats:
Mock.Onregisters a regex-free literal-string match on the method name. Typos compile silently.- The mock relies on reflection at call sites — there is no compile-time type checking of arguments.
- Pre-
v2, the import path isgithub.com/stretchr/testify. There is av2planning issue; check the repository before pinning.
Reference: https://pkg.go.dev/github.com/stretchr/testify/mock
github.com/vektra/mockery¶
A code generator that produces testify/mock-compatible mocks from interface declarations.
Two operating modes:
- Legacy / CLI flags —
mockery --name MyInterface --dir ./internal/repo --output ./mocks. .mockery.yaml(v2.20+, strongly recommended) — declarative configuration.
Example .mockery.yaml:
with-expecter: true
dir: "mocks/{{.PackagePath}}"
filename: "{{.InterfaceName}}.go"
mockname: "{{.InterfaceName}}"
outpkg: "mocks"
packages:
github.com/me/app/internal/repo:
interfaces:
UserRepo:
OrderRepo:
Selected flags / config keys:
| Key | Effect |
|---|---|
with-expecter | Generates a type-safe EXPECT() wrapper around On calls. |
inpackage | Emit mocks into the source package (test-only file). |
outpkg | Mock package name. |
srcpkg | Source package import path. |
case | snake or camel for filenames. |
boilerplate-file | Prepend a license header to generated files. |
disable-version-string | Omit the Code generated by mockery v... line. |
Generated mocks embed mock.Mock so they remain testify-compatible.
Reference: https://vektra.github.io/mockery/
go.uber.org/mock (formerly github.com/golang/mock)¶
golang/mock was archived in June 2023 by the Go team. The community-maintained fork is go.uber.org/mock, with identical API and tool name mockgen.
Generate:
mockgen -source=repo.go -destination=mocks/repo_mock.go -package=mocks
# or reflect mode:
mockgen -destination=mocks/repo_mock.go github.com/me/app/internal/repo UserRepo,OrderRepo
Two generation modes:
- Source mode (
-source): parses one file, generates mocks for every interface in it. Fast, no dependencies, but does not resolve transitive types. - Reflect mode (positional args): builds a small program that imports the target package and uses reflection to emit a mock. Slower but resolves cross-package types correctly.
Core API used in tests:
ctrl := gomock.NewController(t)
defer ctrl.Finish() // not required in Go 1.14+ because of t.Cleanup
m := mocks.NewMockUserRepo(ctrl)
m.EXPECT().FindByID(gomock.Eq("42")).Return(&User{ID: "42"}, nil).Times(1)
m.EXPECT().Save(gomock.Any()).Return(nil)
Matchers: gomock.Eq, gomock.Any, gomock.Not, gomock.Nil, gomock.AssignableToTypeOf, custom via gomock.Matcher interface.
Ordering:
Or .After(otherCall) on a single expectation.
Controller behavior: every unsatisfied expectation fails the test at Finish time; unexpected calls fail immediately. Since v1.5 (Uber fork), gomock.NewController(t) automatically registers a Cleanup so Finish is implicit.
Reference: https://pkg.go.dev/go.uber.org/mock/gomock
github.com/jarcoal/httpmock¶
Replaces the default http.DefaultTransport (or a specific *http.Client's transport) with a registry of responders.
httpmock.Activate()
defer httpmock.DeactivateAndReset()
httpmock.RegisterResponder("GET", "https://api.example.com/users/1",
httpmock.NewStringResponder(200, `{"id":1}`))
Notable APIs:
httpmock.ActivateNonDefault(client)— scope to a specific*http.Client.httpmock.NewJsonResponder(status, body)— JSON helper.httpmock.RegisterRegexpResponder— pattern URLs.httpmock.GetCallCountInfo()— assertion on how many times each responder fired.
Caveat: it monkey-patches the transport. In parallel tests sharing http.DefaultTransport this leaks; prefer ActivateNonDefault with an injected client.
Reference: https://pkg.go.dev/github.com/jarcoal/httpmock
net/http/httptest¶
Standard-library alternative for HTTP integration:
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(200)
fmt.Fprintln(w, `{"ok":true}`)
}))
defer srv.Close()
Pros: real HTTP, no monkey-patching, parallel-safe. Cons: you write the handler each time.
httptest.NewRecorder() is used to test handlers directly without spinning a server.
Reference: https://pkg.go.dev/net/http/httptest
github.com/DATA-DOG/go-sqlmock¶
A driver that implements database/sql/driver.Driver and records expectations on SQL statements:
db, mock, err := sqlmock.New()
mock.ExpectQuery("SELECT id, name FROM users WHERE id = ?").
WithArgs(42).
WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(42, "Ada"))
Two query-matching modes:
sqlmock.QueryMatcherEqual— strict equality.sqlmock.QueryMatcherRegexp(default) — regex match.
Caveats: tests SQL strings, not DB behavior. Does not catch schema mismatches, dialect differences, or transaction-isolation bugs.
Reference: https://pkg.go.dev/github.com/DATA-DOG/go-sqlmock
Fork history and lineage¶
| Repo | Status | Notes |
|---|---|---|
github.com/golang/mock | Archived 2023-06 | Maintained by Google, then handed off. Do not use new. |
go.uber.org/mock | Active | Drop-in replacement. Same mockgen binary name. Same API. |
github.com/stretchr/testify | Active | v1 stable; v2 planning. |
github.com/vektra/mockery | Active | v2 stable; v3 in active development as of 2024-2025. |
github.com/matryer/moq | Active | Generates minimal mocks (no framework dependency). |
github.com/jarcoal/httpmock | Active | Stable; widely used. |
If you read older blog posts referring to github.com/golang/mock/gomock, mentally substitute go.uber.org/mock/gomock. The import path is the only meaningful difference.
Compatibility matrix¶
| Tool | Go min version | Generics support | Generates code | Runtime reflection |
|---|---|---|---|---|
| Hand-rolled stub | any | yes (Go 1.18+) | no | no |
testify/mock | 1.17+ | partial | no | yes |
mockery v2 | 1.18+ | yes (v2.20+) | yes | uses testify at runtime |
gomock (uber) | 1.18+ | yes (v0.4.0+) | yes | minimal |
moq | 1.18+ | yes | yes | no |
sqlmock | 1.13+ | n/a | no | no |
httpmock | 1.13+ | n/a | no | no |
For new projects in 2024-2026, the typical mainstream choice is either:
- Hand-rolled stubs for small interfaces, OR
mockery+testify/mockfor medium codebases with mostly assertion-style tests, ORgomock(uber) for codebases that want strict expectation-style tests with compile-time type safety.
Avoid mixing two mock frameworks in the same package; readers should not have to context-switch between EXPECT() and On() in adjacent files.