Limitations¶
The items below apply to compile-time function and method mocking (toolexec). Interface mock generation (rewire.NewMock[T]) has no documented limitations at this time — see Interface Mocks for the full feature set.
Per-instance method stubs are fully supported natively — see Per-instance method mocks.
Compiler intrinsics¶
Functions like math.Abs, math.Sqrt, and math.Floor are replaced with CPU instructions by the Go compiler at the call site. Even though rewire rewrites the function body, callers bypass it entirely — the compiler emits hardware instructions (e.g., FABS on arm64) instead of a function call.
Rewire detects these automatically and fails with a clear error message. Use non-intrinsic alternatives where possible (e.g., math.Pow works fine).
No parallel mock safety¶
Parallel tests in the same package should not mock the same function with different replacements. The mock variable is shared, so two parallel tests setting it will race.
Two parallel tests mocking different functions is fine — there's no contention.
Note
This only matters for tests using t.Parallel(). Sequential tests (the default) don't have this issue since t.Cleanup restores the original between tests.
Bodyless functions¶
Functions implemented in assembly (no Go body) cannot be rewritten. These are typically low-level runtime or math functions. Rewire will fail with an error if you try to mock one.
Build cache and new mock targets¶
When you add a new rewire.Func target for a package that was already cached (e.g., adding rewire.Func(t, os.Hostname, ...) when only os.Getwd was mocked before), the cached .a file for that package lacks the new Mock_/Real_ variables. Rewire detects this automatically and clears the build cache, printing:
rewire: mock target set changed (affected packages: os, strings, ...).
The build cache has been cleared automatically.
Please re-run your test command — the next run will succeed.
Why a re-run is needed: rewriting os changes its linker fingerprint. Every package compiled against the old os (including testing, fmt, etc.) embeds that fingerprint. The linker rejects mismatches, so the entire transitive dependency tree must be rebuilt — equivalent to clearing the cache. This only happens when the set of mocked functions changes, not during normal TDD.
If you change rewire versions, you may also need to clean the cache manually:
Using a separate test cache (GOCACHE) avoids conflicts between go build and go test. See Setup for details.