A tool for generating self-contained, type-safe test doubles in go
Go
1,142
718 commits
updated Oct 6, 2026
counterfeiter Go code declares what it needs from its dependencies as interfaces, usually small ones defined by the package that uses them. Testing that code means supplying fake implementations of those interfaces. Go has no way to build one at runtime, so they are written by hand or generated.
counterfeiter generates test doubles for a given interface. Given this:
package foo
//go:generate go tool counterfeiter -generate
//counterfeiter:generate . MySpecialInterface
type MySpecialInterface interface {
DoThings(string, uint64) (int, error)
}
go generate writes foofakes/fake_my_special_interface.go, and your tests can do this:
fake := &foofakes.FakeMySpecialInterface{}
fake.DoThingsReturns(3, nil)
num, err := fake.DoThings("stuff", 5)
Expect(num).To(Equal(3))
Expect(fake.DoThingsCallCount()).To(Equal(1))
str, _ := fake.DoThingsArgsForCall(0)
Expect(str).To(Equal("stuff"))
counterfeiter is run by go generate, so fakes are regenerated alongside the code they fake. The steps below assume go 1.24 or later, which added go tool; for older versions of go, refer to an older version of this README.
counterfeiter as a tool dependencyEstablish a tool dependency on counterfeiter by running the following command:
go get -tool github.com/maxbrunsfeld/counterfeiter/v6
Add one go:generate directive per package that runs counterfeiter -generate, and one counterfeiter:generate directive per interface you want a fake for. You can add them right next to your interface definitions (or not), in any .go file in the package.
In myinterface.go:
package foo
// You only need **one** of these per package!
//go:generate go tool counterfeiter -generate
// You will add lots of directives like these in the same package...
//counterfeiter:generate . MySpecialInterface
type MySpecialInterface interface {
DoThings(string, uint64) (int, error)
}
// Like this...
//counterfeiter:generate . MyOtherInterface
type MyOtherInterface interface {
DoOtherThings(string, uint64) (int, error)
}
A counterfeiter:generate directive takes the same arguments as the command line: the directory of the package that declares the interface (. for the package the directive is in) and the name of the interface, plus any of the flags described below.
If a package only has an interface or two, you can skip -generate and the counterfeiter:generate directives, and run counterfeiter directly from one go:generate line per interface instead:
//go:generate go tool counterfeiter . MySpecialInterface
-generate is much faster once there are several directives in a package, because it loads the package once and writes every fake from one process, where each go:generate line starts a new one.
go generateYou can run go generate in the directory with your directive, or in the root of your module (to ensure you generate for all packages in your module):
$ go generate ./...
Writing `FakeMySpecialInterface` to `foofakes/fake_my_special_interface.go`... Done
Writing `FakeMyOtherInterface` to `foofakes/fake_my_other_interface.go`... Done
MySpecialInterface above is declared in package foo, so //counterfeiter:generate . MySpecialInterface produces:
| default | change it with | |
|---|---|---|
| fake type | FakeMySpecialInterface (Fake + the interface name) | -fake-name, -fake-name-template |
| file | fake_my_special_interface.go (the fake's name in snake case) | -o <path>.go |
| directory | foofakes/ (<package>fakes, beside the package that declares the interface) | -o <dir> |
| package | foofakes (<package>fakes), or whatever package already lives in the output directory | -o, -test, or a file declaring the package |
Every fake ends with a compile-time assertion that it satisfies the interface, so when the interface changes, the stale fake stops compiling until you run go generate again.
The examples below are counterfeiter:generate directives, and assume the package has the //go:generate go tool counterfeiter -generate line from Step 2. A package needs only one of those, no matter how many directives it has.
Flags given alongside -generate on the //go:generate line are the defaults for every //counterfeiter:generate directive in the package: -o, -header, -q, -test and -fake-name-template. A directive's own flags take precedence. So if you would rather keep all of a package's fakes in a fake package, named after their interfaces, you can write that once:
//go:generate go tool counterfeiter -generate -o fake -fake-name-template '{{.TargetName}}'
//counterfeiter:generate . MyRepository
//counterfeiter:generate . MyPresenter
$ go generate ./...
Writing `MyRepository` to `fake/my_repository.go`... Done
Writing `MyPresenter` to `fake/my_presenter.go`... Done
You can fake any interface your module can import. A third-party module has to be a dependency first (go get it, so it appears in your go.mod), since counterfeiter loads the interface from the module cache the same way the compiler would. Name the interface as <package-path>.<interface>, or give the directory of the package and the interface name:
//counterfeiter:generate io.WriteCloser
//counterfeiter:generate github.com/redis/go-redis/v9.Pipeliner
//counterfeiter:generate ../otherpackage OtherInterface
The two forms differ in where the fake goes. With <package-path>.<interface>, it goes into the fakes package of the directory the directive is in, so in package foo the first line writes foofakes/fake_write_closer.go. With a directory and an interface name, it goes into the fakes package beside that directory, so the third line writes ../otherpackage/otherpackagefakes/fake_other_interface.go. Use -o to put it somewhere else.
By default the fake lives in a sibling <package>fakes package. Tests in <package> itself cannot import it, because <package>fakes imports <package> and that would be an import cycle. To use a fake in those tests, point -o at the interface's own directory:
//counterfeiter:generate -o . . MySpecialInterface
When the output directory is the directory of the package that declares the interface, counterfeiter generates the fake as a member of that package: it does not import the package, refers to its types unqualified, and can fake unexported interfaces too, in which case the fake is unexported as well (gadget gets fakeGadget) unless -fake-name names it. -o may also name a file in that directory, for example -o fake_my_special_interface_test.go to keep the fake out of the non-test build.
<package>_testGo lets a directory hold a second package for tests, <package>_test, which imports <package> and sees only its exported API. If your tests are in it, -test generates the fake into that external test package instead, as a _test.go file in the current directory, next to the tests that use it:
//counterfeiter:generate -test . MySpecialInterface
//counterfeiter:generate -test ../otherpackage OtherInterface
//counterfeiter:generate -test io.WriteCloser
In package foo, all three of these write a _test.go file into the current directory, in package foo_test: fake_my_special_interface_test.go, fake_other_interface_test.go and fake_write_closer_test.go. With -test the fake goes into the package the directive is in, not the package that declares the interface, so faking OtherInterface writes nothing into ../otherpackage. The fakes are only compiled for tests, and the tests use them unqualified (&FakeMySpecialInterface{}). The interface's package is imported as usual, so the interface must be exported. With -o <dir> the fake goes into the external test package of that directory instead.
If the output directory already contains Go files, the fake joins that package. If it is empty, the fake's package is named after the directory. So to name the package differently from its directory, say impl_fakes in fakes/, add a file declaring that package first:
// fakes/doc.go
package impl_fakes
//counterfeiter:generate -o fakes . MyInterface
-fake-name names one fake. -fake-name-template is a Go text/template in which {{.TargetName}} is the name of the interface being faked (first letter upper-cased); it applies wherever -fake-name is not given, and can be set once for the package on the -generate line. The file name follows the fake's name.
//counterfeiter:generate -fake-name Repo . MyRepository
//counterfeiter:generate -fake-name-template '{{.TargetName}}Double' . MyPresenter
$ go generate ./...
Writing `Repo` to `foofakes/repo.go`... Done
Writing `MyPresenterDouble` to `foofakes/my_presenter_double.go`... Done
-header prepends the contents of a file to every generated fake, for a licence header for example. Set it once on the -generate line, or per directive.
//go:generate go tool counterfeiter -generate -header ../LICENSE.header
Function types can be faked as well. The fake is a struct whose Spy method has the function's signature, so fake.Spy goes wherever the function is expected. Returns, CallCount, ArgsForCall, Args and the rest work as for a method, without a method name in front; the arguments struct is FakeRequestHandlerArgs.
//counterfeiter:generate . RequestHandler
type RequestHandler func(*http.Request) error
fake := &foofakes.FakeRequestHandler{}
fake.Returns(nil)
server := NewServer(fake.Spy)
Package mode, -p, is for code that calls package-level functions directly, os.Hostname() say, and has no interface to fake. It writes a file with an interface whose methods are the package's exported functions, and a shim struct that forwards each method to the package. The file carries a counterfeiter:generate directive of its own, so the next go generate produces a fake of that interface.
//counterfeiter:generate -p os
$ go generate ./...
Writing `Os` to `osshim/os.go`... Done
$ go generate ./...
Writing `FakeOs` to `osshimfakes/fake_os.go`... Done
Your code takes the osshim.Os interface, production code passes &osshim.OsShim{}, tests pass the fake.
A trailing - prints the fake to standard output instead of writing a file:
$ go tool counterfeiter . MySpecialInterface -
-q drops the Writing ... lines, which is useful in a -generate line for a package with many fakes.
Instantiate fakes:
import "my-repo/path/to/foo/foofakes"
var fake = &foofakes.FakeMySpecialInterface{}
For each method <Method> of the interface, the fake has:
<Method>Returns, <Method>ReturnsOnCall | stub what it returns |
<Method>Calls, <Method>Stub | replace it with a function |
<Method>CallCount, <Method>ArgsForCall, <Method>Args | inspect the calls it received |
You can stub return values:
fake.DoThingsReturns(3, errors.New("the-error"))
num, err := fake.DoThings("stuff", 5)
Expect(num).To(Equal(3))
Expect(err).To(Equal(errors.New("the-error")))
or stub them for one call at a time, counting from zero; calls without an entry fall back to Returns:
fake.DoThingsReturnsOnCall(0, 1, nil)
fake.DoThingsReturnsOnCall(1, 0, errors.New("the-error"))
When the result depends on the arguments, give the fake a function instead. It takes precedence over Returns and ReturnsOnCall, and calling either of those clears it again:
fake.DoThingsCalls(func(s string, n uint64) (int, error) {
if s == "stuff" {
return 3, nil
}
return 0, errors.New("unexpected")
})
DoThingsCalls stores the function in the exported DoThingsStub field while holding the fake's lock, so it is safe even if other goroutines are already calling the fake. Setting the field directly is only useful in a struct literal, &foofakes.FakeMySpecialInterface{DoThingsStub: ...}. Without a stub or stubbed return values, the fake returns zero values.
Fakes record the arguments they were called with:
fake.DoThings("stuff", 5)
Expect(fake.DoThingsCallCount()).To(Equal(1))
str, num := fake.DoThingsArgsForCall(0)
Expect(str).To(Equal("stuff"))
Expect(num).To(Equal(uint64(5)))
DoThingsArgs returns every call as a slice of structs instead, one exported field per argument, so a whole call can be compared in one assertion with gomega's Equal or with go-cmp. The struct is named after the fake and the method, FakeMySpecialInterfaceDoThingsArgs, and a variadic parameter becomes a slice field:
fake.DoThings("stuff", 5)
fake.DoThings("more", 6)
Expect(fake.DoThingsArgs()).To(Equal([]foofakes.FakeMySpecialInterfaceDoThingsArgs{
{Arg1: "stuff", Arg2: 5},
{Arg1: "more", Arg2: 6},
}))
CallOrder() returns the names of a fake's methods in the order they were called, for when that order is part of the contract, like a write that has to land before the commit: Expect(tx.CallOrder()).To(Equal([]string{"Write", "Commit"})).
Slice and array arguments are recorded as copies, so a caller that reuses its buffer does not change what the fake recorded; a stub function still receives the original. fake.Invocations() returns every recorded call of every method, keyed by method name. Fakes are safe to use from several goroutines at once.
For more examples of using the counterfeiter API, look at some of the provided examples. If you are moving from gomock, docs/migrating-from-gomock.md goes through the differences.
go tool counterfeiter -help prints the following. Outside a module, go install github.com/maxbrunsfeld/counterfeiter/v6@latest puts a counterfeiter binary in $GOPATH/bin that takes the same arguments.
USAGE
counterfeiter
[-generate] [-o <output-path>] [-p] [-fake-name <fake-name>]
[-fake-name-template <template>] [-header <header-file>] [-q] [-test]
[<source-path>] <interface> [-]
ARGUMENTS
source-path
Path to the file or directory containing the interface to fake.
In package mode (-p), source-path is the import path of the package
to generate an interface and shim for; a standard library package
can be given by name (e.g. "os").
interface
If source-path is specified: name of the interface to fake.
If no source-path is specified: fully qualified path of the
interface to fake, <package-path>.<interface>.
Not used in package mode (-p), where the interface is named after
the package.
example:
# in directory "mypackage", writes "FakeStdInterface" to
# ./mypackagefakes/fake_std_interface.go
counterfeiter package/subpackage.StdInterface
'-' argument
Write code to standard out instead of to a file
OPTIONS
-generate
Identify all //counterfeiter:generate directives in .go files in the
current working directory and generate fakes for them. You can pass
arguments as usual.
NOTE: This is not the same as //go:generate directives
(used with the 'go generate' command), but it can be combined with
go generate by adding the following to a .go file:
# runs counterfeiter in generate mode
//go:generate go tool counterfeiter -generate
example:
Add the following to a .go file:
//counterfeiter:generate . MyInterface
//counterfeiter:generate . MyOtherInterface
//counterfeiter:generate . MyThirdInterface
# run counterfeiter
counterfeiter -generate
# writes "FakeMyInterface" to ./mypackagefakes/fake_my_interface.go
# writes "FakeMyOtherInterface" to ./mypackagefakes/fake_my_other_interface.go
# writes "FakeMyThirdInterface" to ./mypackagefakes/fake_my_third_interface.go
The -o, -fake-name-template, -header, -q and -test flags given
alongside -generate are the defaults for every directive. A directive's
own flags take precedence.
example:
# every fake goes into ./fake and is named after its interface
//go:generate go tool counterfeiter -generate -o fake -fake-name-template {{.TargetName}}
//counterfeiter:generate . MyInterface
//counterfeiter:generate -o otherfake . MyOtherInterface
# writes "MyInterface" to ./fake/my_interface.go
# writes "MyOtherInterface" to ./otherfake/my_other_interface.go
-o
Path to the file or directory for the generated fakes.
This also determines the package name that will be used:
if the directory already holds a Go package the fake joins
it, otherwise the package is named after the directory.
By default, the generated fakes will be generated in
the package "xyzfakes" which is nested in package "xyz",
where "xyz" is the name of referenced package.
example:
# writes "FakeMyInterface" to ./mySpecialFakesDir/specialFake.go
counterfeiter -o ./mySpecialFakesDir/specialFake.go ./mypackage MyInterface
# writes "FakeMyInterface" to ./mySpecialFakesDir/fake_my_interface.go
counterfeiter -o ./mySpecialFakesDir ./mypackage MyInterface
-test
Generate the fake into the external test package ("<package>_test")
of the output directory, in a _test.go file, so it is only compiled
for tests and tests in that package can use it unqualified. Without -o the
fake is written into the current directory, next to the tests that
use it, wherever the interface comes from. The interface's package
is imported as usual, so the interface must be exported.
Cannot be combined with -p.
example:
# writes "FakeMyInterface" to ./fake_my_interface_test.go, in package "mypackage_test"
counterfeiter -test . MyInterface
# writes "FakeOtherInterface" to ./fake_other_interface_test.go, in package "mypackage_test"
counterfeiter -test ../otherpackage OtherInterface
# writes "FakeWriteCloser" to ./fake_write_closer_test.go, in package "mypackage_test"
counterfeiter -test io.WriteCloser
-p
Package mode: counterfeiter generates an interface and a shim
implementation for a package in your module or the standard
library. The interface has the package's exported functions as
methods, and the shim forwards each method to the package. The
generated file carries a //counterfeiter:generate directive, so
running go generate there produces a fake of the interface.
example:
# writes the "Os" interface and "OsShim" to ${PWD}/osshim/os.go
counterfeiter -p os
# now generate "FakeOs" in ${PWD}/osshim/osshimfakes/fake_os.go
go generate ./osshim/...
-header
Path to the file which should be used as a header for all generated fakes.
By default, no special header is used.
This is useful to e.g. add a licence header to every fake.
In generate mode the header can be set once for the whole package on
the "go:generate" line; a "counterfeiter:generate" line that specifies
its own header file takes precedence.
example:
# having the following code in a package ...
//go:generate go tool counterfeiter -header ./generic.go.txt -generate
//counterfeiter:generate -header ./specific.go.txt . MyInterface
//counterfeiter:generate . MyOtherInterface
//counterfeiter:generate . MyThirdInterface
# ... generating the fakes ...
go generate .
# writes "FakeMyInterface" with ./specific.go.txt as a header
# writes "FakeMyOtherInterface" & "FakeMyThirdInterface" with ./generic.go.txt as a header
-fake-name
Name of the fake struct to generate, used as given. By default,
'Fake' will be prepended to the name of the original interface;
a fake of an unexported interface generated into the interface's
own package is unexported. (ignored in -p mode)
example:
# writes "CoolThing" to ./mypackagefakes/cool_thing.go
counterfeiter -fake-name CoolThing ./mypackage MyInterface
-fake-name-template
A text/template for the name of the fake struct, used when -fake-name
is not given. {{.TargetName}} is the name of the interface being faked,
with its first letter upper-cased. In generate mode it can be set once
for the whole package on the "go:generate" line. (ignored in -p mode)
example:
# writes "MyInterfaceDouble" to ./mypackagefakes/my_interface_double.go
counterfeiter -fake-name-template '{{.TargetName}}Double' ./mypackage MyInterface
-q
Suppress the "Writing ..." status lines. Errors are still reported.
gocounterfeiter follows the support policy of go itself:
Each major Go release is supported until there are two newer major releases. For example, Go 1.5 was supported until the Go 1.7 release, and Go 1.6 was supported until the Go 1.8 release. We fix critical problems, including critical security problems, in supported releases as needed by issuing minor revisions (for example, Go 1.6.1, Go 1.6.2, and so on).
If you are having problems with counterfeiter and are not using a supported version of go, please update to use a supported version of go before opening an issue.
counterfeiterIf you want to run the tests for counterfeiter (perhaps, because you want to contribute a PR), all you have to do is run scripts/ci.sh (scripts/ci.ps1 on Windows).
So you want to contribute to counterfeiter! That's great, here's what to do:
counterfeiter has a few high level goals for contributors to keep in mind
main.go as simple as possiblecounterfeiter any more complicatedIf you have any questions about how to contribute, @joefitzgerald maintains counterfeiter and will work with you to make it better, together. This project has largely been maintained by the community, and we greatly appreciate any PR (whether big or small).
counterfeiter is MIT-licensed.
(top 24 of 27)
988 followers · starred Jan 2020
1,927 followers · starred May 2023
2,014 followers · starred Nov 2014
252 followers · starred Dec 2025
A tool for generating self-contained, type-safe test doubles in go
Go
1,142
718 commits
updated Oct 6, 2026
counterfeiter Go code declares what it needs from its dependencies as interfaces, usually small ones defined by the package that uses them. Testing that code means supplying fake implementations of those interfaces. Go has no way to build one at runtime, so they are written by hand or generated.
counterfeiter generates test doubles for a given interface. Given this:
package foo
//go:generate go tool counterfeiter -generate
//counterfeiter:generate . MySpecialInterface
type MySpecialInterface interface {
DoThings(string, uint64) (int, error)
}
go generate writes foofakes/fake_my_special_interface.go, and your tests can do this:
fake := &foofakes.FakeMySpecialInterface{}
fake.DoThingsReturns(3, nil)
num, err := fake.DoThings("stuff", 5)
Expect(num).To(Equal(3))
Expect(fake.DoThingsCallCount()).To(Equal(1))
str, _ := fake.DoThingsArgsForCall(0)
Expect(str).To(Equal("stuff"))
counterfeiter is run by go generate, so fakes are regenerated alongside the code they fake. The steps below assume go 1.24 or later, which added go tool; for older versions of go, refer to an older version of this README.
counterfeiter as a tool dependencyEstablish a tool dependency on counterfeiter by running the following command:
go get -tool github.com/maxbrunsfeld/counterfeiter/v6
Add one go:generate directive per package that runs counterfeiter -generate, and one counterfeiter:generate directive per interface you want a fake for. You can add them right next to your interface definitions (or not), in any .go file in the package.
In myinterface.go:
package foo
// You only need **one** of these per package!
//go:generate go tool counterfeiter -generate
// You will add lots of directives like these in the same package...
//counterfeiter:generate . MySpecialInterface
type MySpecialInterface interface {
DoThings(string, uint64) (int, error)
}
// Like this...
//counterfeiter:generate . MyOtherInterface
type MyOtherInterface interface {
DoOtherThings(string, uint64) (int, error)
}
A counterfeiter:generate directive takes the same arguments as the command line: the directory of the package that declares the interface (. for the package the directive is in) and the name of the interface, plus any of the flags described below.
If a package only has an interface or two, you can skip -generate and the counterfeiter:generate directives, and run counterfeiter directly from one go:generate line per interface instead:
//go:generate go tool counterfeiter . MySpecialInterface
-generate is much faster once there are several directives in a package, because it loads the package once and writes every fake from one process, where each go:generate line starts a new one.
go generateYou can run go generate in the directory with your directive, or in the root of your module (to ensure you generate for all packages in your module):
$ go generate ./...
Writing `FakeMySpecialInterface` to `foofakes/fake_my_special_interface.go`... Done
Writing `FakeMyOtherInterface` to `foofakes/fake_my_other_interface.go`... Done
MySpecialInterface above is declared in package foo, so //counterfeiter:generate . MySpecialInterface produces:
| default | change it with | |
|---|---|---|
| fake type | FakeMySpecialInterface (Fake + the interface name) | -fake-name, -fake-name-template |
| file | fake_my_special_interface.go (the fake's name in snake case) | -o <path>.go |
| directory | foofakes/ (<package>fakes, beside the package that declares the interface) | -o <dir> |
| package | foofakes (<package>fakes), or whatever package already lives in the output directory | -o, -test, or a file declaring the package |
Every fake ends with a compile-time assertion that it satisfies the interface, so when the interface changes, the stale fake stops compiling until you run go generate again.
The examples below are counterfeiter:generate directives, and assume the package has the //go:generate go tool counterfeiter -generate line from Step 2. A package needs only one of those, no matter how many directives it has.
Flags given alongside -generate on the //go:generate line are the defaults for every //counterfeiter:generate directive in the package: -o, -header, -q, -test and -fake-name-template. A directive's own flags take precedence. So if you would rather keep all of a package's fakes in a fake package, named after their interfaces, you can write that once:
//go:generate go tool counterfeiter -generate -o fake -fake-name-template '{{.TargetName}}'
//counterfeiter:generate . MyRepository
//counterfeiter:generate . MyPresenter
$ go generate ./...
Writing `MyRepository` to `fake/my_repository.go`... Done
Writing `MyPresenter` to `fake/my_presenter.go`... Done
You can fake any interface your module can import. A third-party module has to be a dependency first (go get it, so it appears in your go.mod), since counterfeiter loads the interface from the module cache the same way the compiler would. Name the interface as <package-path>.<interface>, or give the directory of the package and the interface name:
//counterfeiter:generate io.WriteCloser
//counterfeiter:generate github.com/redis/go-redis/v9.Pipeliner
//counterfeiter:generate ../otherpackage OtherInterface
The two forms differ in where the fake goes. With <package-path>.<interface>, it goes into the fakes package of the directory the directive is in, so in package foo the first line writes foofakes/fake_write_closer.go. With a directory and an interface name, it goes into the fakes package beside that directory, so the third line writes ../otherpackage/otherpackagefakes/fake_other_interface.go. Use -o to put it somewhere else.
By default the fake lives in a sibling <package>fakes package. Tests in <package> itself cannot import it, because <package>fakes imports <package> and that would be an import cycle. To use a fake in those tests, point -o at the interface's own directory:
//counterfeiter:generate -o . . MySpecialInterface
When the output directory is the directory of the package that declares the interface, counterfeiter generates the fake as a member of that package: it does not import the package, refers to its types unqualified, and can fake unexported interfaces too, in which case the fake is unexported as well (gadget gets fakeGadget) unless -fake-name names it. -o may also name a file in that directory, for example -o fake_my_special_interface_test.go to keep the fake out of the non-test build.
<package>_testGo lets a directory hold a second package for tests, <package>_test, which imports <package> and sees only its exported API. If your tests are in it, -test generates the fake into that external test package instead, as a _test.go file in the current directory, next to the tests that use it:
//counterfeiter:generate -test . MySpecialInterface
//counterfeiter:generate -test ../otherpackage OtherInterface
//counterfeiter:generate -test io.WriteCloser
In package foo, all three of these write a _test.go file into the current directory, in package foo_test: fake_my_special_interface_test.go, fake_other_interface_test.go and fake_write_closer_test.go. With -test the fake goes into the package the directive is in, not the package that declares the interface, so faking OtherInterface writes nothing into ../otherpackage. The fakes are only compiled for tests, and the tests use them unqualified (&FakeMySpecialInterface{}). The interface's package is imported as usual, so the interface must be exported. With -o <dir> the fake goes into the external test package of that directory instead.
If the output directory already contains Go files, the fake joins that package. If it is empty, the fake's package is named after the directory. So to name the package differently from its directory, say impl_fakes in fakes/, add a file declaring that package first:
// fakes/doc.go
package impl_fakes
//counterfeiter:generate -o fakes . MyInterface
-fake-name names one fake. -fake-name-template is a Go text/template in which {{.TargetName}} is the name of the interface being faked (first letter upper-cased); it applies wherever -fake-name is not given, and can be set once for the package on the -generate line. The file name follows the fake's name.
//counterfeiter:generate -fake-name Repo . MyRepository
//counterfeiter:generate -fake-name-template '{{.TargetName}}Double' . MyPresenter
$ go generate ./...
Writing `Repo` to `foofakes/repo.go`... Done
Writing `MyPresenterDouble` to `foofakes/my_presenter_double.go`... Done
-header prepends the contents of a file to every generated fake, for a licence header for example. Set it once on the -generate line, or per directive.
//go:generate go tool counterfeiter -generate -header ../LICENSE.header
Function types can be faked as well. The fake is a struct whose Spy method has the function's signature, so fake.Spy goes wherever the function is expected. Returns, CallCount, ArgsForCall, Args and the rest work as for a method, without a method name in front; the arguments struct is FakeRequestHandlerArgs.
//counterfeiter:generate . RequestHandler
type RequestHandler func(*http.Request) error
fake := &foofakes.FakeRequestHandler{}
fake.Returns(nil)
server := NewServer(fake.Spy)
Package mode, -p, is for code that calls package-level functions directly, os.Hostname() say, and has no interface to fake. It writes a file with an interface whose methods are the package's exported functions, and a shim struct that forwards each method to the package. The file carries a counterfeiter:generate directive of its own, so the next go generate produces a fake of that interface.
//counterfeiter:generate -p os
$ go generate ./...
Writing `Os` to `osshim/os.go`... Done
$ go generate ./...
Writing `FakeOs` to `osshimfakes/fake_os.go`... Done
Your code takes the osshim.Os interface, production code passes &osshim.OsShim{}, tests pass the fake.
A trailing - prints the fake to standard output instead of writing a file:
$ go tool counterfeiter . MySpecialInterface -
-q drops the Writing ... lines, which is useful in a -generate line for a package with many fakes.
Instantiate fakes:
import "my-repo/path/to/foo/foofakes"
var fake = &foofakes.FakeMySpecialInterface{}
For each method <Method> of the interface, the fake has:
<Method>Returns, <Method>ReturnsOnCall | stub what it returns |
<Method>Calls, <Method>Stub | replace it with a function |
<Method>CallCount, <Method>ArgsForCall, <Method>Args | inspect the calls it received |
You can stub return values:
fake.DoThingsReturns(3, errors.New("the-error"))
num, err := fake.DoThings("stuff", 5)
Expect(num).To(Equal(3))
Expect(err).To(Equal(errors.New("the-error")))
or stub them for one call at a time, counting from zero; calls without an entry fall back to Returns:
fake.DoThingsReturnsOnCall(0, 1, nil)
fake.DoThingsReturnsOnCall(1, 0, errors.New("the-error"))
When the result depends on the arguments, give the fake a function instead. It takes precedence over Returns and ReturnsOnCall, and calling either of those clears it again:
fake.DoThingsCalls(func(s string, n uint64) (int, error) {
if s == "stuff" {
return 3, nil
}
return 0, errors.New("unexpected")
})
DoThingsCalls stores the function in the exported DoThingsStub field while holding the fake's lock, so it is safe even if other goroutines are already calling the fake. Setting the field directly is only useful in a struct literal, &foofakes.FakeMySpecialInterface{DoThingsStub: ...}. Without a stub or stubbed return values, the fake returns zero values.
Fakes record the arguments they were called with:
fake.DoThings("stuff", 5)
Expect(fake.DoThingsCallCount()).To(Equal(1))
str, num := fake.DoThingsArgsForCall(0)
Expect(str).To(Equal("stuff"))
Expect(num).To(Equal(uint64(5)))
DoThingsArgs returns every call as a slice of structs instead, one exported field per argument, so a whole call can be compared in one assertion with gomega's Equal or with go-cmp. The struct is named after the fake and the method, FakeMySpecialInterfaceDoThingsArgs, and a variadic parameter becomes a slice field:
fake.DoThings("stuff", 5)
fake.DoThings("more", 6)
Expect(fake.DoThingsArgs()).To(Equal([]foofakes.FakeMySpecialInterfaceDoThingsArgs{
{Arg1: "stuff", Arg2: 5},
{Arg1: "more", Arg2: 6},
}))
CallOrder() returns the names of a fake's methods in the order they were called, for when that order is part of the contract, like a write that has to land before the commit: Expect(tx.CallOrder()).To(Equal([]string{"Write", "Commit"})).
Slice and array arguments are recorded as copies, so a caller that reuses its buffer does not change what the fake recorded; a stub function still receives the original. fake.Invocations() returns every recorded call of every method, keyed by method name. Fakes are safe to use from several goroutines at once.
For more examples of using the counterfeiter API, look at some of the provided examples. If you are moving from gomock, docs/migrating-from-gomock.md goes through the differences.
go tool counterfeiter -help prints the following. Outside a module, go install github.com/maxbrunsfeld/counterfeiter/v6@latest puts a counterfeiter binary in $GOPATH/bin that takes the same arguments.
USAGE
counterfeiter
[-generate] [-o <output-path>] [-p] [-fake-name <fake-name>]
[-fake-name-template <template>] [-header <header-file>] [-q] [-test]
[<source-path>] <interface> [-]
ARGUMENTS
source-path
Path to the file or directory containing the interface to fake.
In package mode (-p), source-path is the import path of the package
to generate an interface and shim for; a standard library package
can be given by name (e.g. "os").
interface
If source-path is specified: name of the interface to fake.
If no source-path is specified: fully qualified path of the
interface to fake, <package-path>.<interface>.
Not used in package mode (-p), where the interface is named after
the package.
example:
# in directory "mypackage", writes "FakeStdInterface" to
# ./mypackagefakes/fake_std_interface.go
counterfeiter package/subpackage.StdInterface
'-' argument
Write code to standard out instead of to a file
OPTIONS
-generate
Identify all //counterfeiter:generate directives in .go files in the
current working directory and generate fakes for them. You can pass
arguments as usual.
NOTE: This is not the same as //go:generate directives
(used with the 'go generate' command), but it can be combined with
go generate by adding the following to a .go file:
# runs counterfeiter in generate mode
//go:generate go tool counterfeiter -generate
example:
Add the following to a .go file:
//counterfeiter:generate . MyInterface
//counterfeiter:generate . MyOtherInterface
//counterfeiter:generate . MyThirdInterface
# run counterfeiter
counterfeiter -generate
# writes "FakeMyInterface" to ./mypackagefakes/fake_my_interface.go
# writes "FakeMyOtherInterface" to ./mypackagefakes/fake_my_other_interface.go
# writes "FakeMyThirdInterface" to ./mypackagefakes/fake_my_third_interface.go
The -o, -fake-name-template, -header, -q and -test flags given
alongside -generate are the defaults for every directive. A directive's
own flags take precedence.
example:
# every fake goes into ./fake and is named after its interface
//go:generate go tool counterfeiter -generate -o fake -fake-name-template {{.TargetName}}
//counterfeiter:generate . MyInterface
//counterfeiter:generate -o otherfake . MyOtherInterface
# writes "MyInterface" to ./fake/my_interface.go
# writes "MyOtherInterface" to ./otherfake/my_other_interface.go
-o
Path to the file or directory for the generated fakes.
This also determines the package name that will be used:
if the directory already holds a Go package the fake joins
it, otherwise the package is named after the directory.
By default, the generated fakes will be generated in
the package "xyzfakes" which is nested in package "xyz",
where "xyz" is the name of referenced package.
example:
# writes "FakeMyInterface" to ./mySpecialFakesDir/specialFake.go
counterfeiter -o ./mySpecialFakesDir/specialFake.go ./mypackage MyInterface
# writes "FakeMyInterface" to ./mySpecialFakesDir/fake_my_interface.go
counterfeiter -o ./mySpecialFakesDir ./mypackage MyInterface
-test
Generate the fake into the external test package ("<package>_test")
of the output directory, in a _test.go file, so it is only compiled
for tests and tests in that package can use it unqualified. Without -o the
fake is written into the current directory, next to the tests that
use it, wherever the interface comes from. The interface's package
is imported as usual, so the interface must be exported.
Cannot be combined with -p.
example:
# writes "FakeMyInterface" to ./fake_my_interface_test.go, in package "mypackage_test"
counterfeiter -test . MyInterface
# writes "FakeOtherInterface" to ./fake_other_interface_test.go, in package "mypackage_test"
counterfeiter -test ../otherpackage OtherInterface
# writes "FakeWriteCloser" to ./fake_write_closer_test.go, in package "mypackage_test"
counterfeiter -test io.WriteCloser
-p
Package mode: counterfeiter generates an interface and a shim
implementation for a package in your module or the standard
library. The interface has the package's exported functions as
methods, and the shim forwards each method to the package. The
generated file carries a //counterfeiter:generate directive, so
running go generate there produces a fake of the interface.
example:
# writes the "Os" interface and "OsShim" to ${PWD}/osshim/os.go
counterfeiter -p os
# now generate "FakeOs" in ${PWD}/osshim/osshimfakes/fake_os.go
go generate ./osshim/...
-header
Path to the file which should be used as a header for all generated fakes.
By default, no special header is used.
This is useful to e.g. add a licence header to every fake.
In generate mode the header can be set once for the whole package on
the "go:generate" line; a "counterfeiter:generate" line that specifies
its own header file takes precedence.
example:
# having the following code in a package ...
//go:generate go tool counterfeiter -header ./generic.go.txt -generate
//counterfeiter:generate -header ./specific.go.txt . MyInterface
//counterfeiter:generate . MyOtherInterface
//counterfeiter:generate . MyThirdInterface
# ... generating the fakes ...
go generate .
# writes "FakeMyInterface" with ./specific.go.txt as a header
# writes "FakeMyOtherInterface" & "FakeMyThirdInterface" with ./generic.go.txt as a header
-fake-name
Name of the fake struct to generate, used as given. By default,
'Fake' will be prepended to the name of the original interface;
a fake of an unexported interface generated into the interface's
own package is unexported. (ignored in -p mode)
example:
# writes "CoolThing" to ./mypackagefakes/cool_thing.go
counterfeiter -fake-name CoolThing ./mypackage MyInterface
-fake-name-template
A text/template for the name of the fake struct, used when -fake-name
is not given. {{.TargetName}} is the name of the interface being faked,
with its first letter upper-cased. In generate mode it can be set once
for the whole package on the "go:generate" line. (ignored in -p mode)
example:
# writes "MyInterfaceDouble" to ./mypackagefakes/my_interface_double.go
counterfeiter -fake-name-template '{{.TargetName}}Double' ./mypackage MyInterface
-q
Suppress the "Writing ..." status lines. Errors are still reported.
gocounterfeiter follows the support policy of go itself:
Each major Go release is supported until there are two newer major releases. For example, Go 1.5 was supported until the Go 1.7 release, and Go 1.6 was supported until the Go 1.8 release. We fix critical problems, including critical security problems, in supported releases as needed by issuing minor revisions (for example, Go 1.6.1, Go 1.6.2, and so on).
If you are having problems with counterfeiter and are not using a supported version of go, please update to use a supported version of go before opening an issue.
counterfeiterIf you want to run the tests for counterfeiter (perhaps, because you want to contribute a PR), all you have to do is run scripts/ci.sh (scripts/ci.ps1 on Windows).
So you want to contribute to counterfeiter! That's great, here's what to do:
counterfeiter has a few high level goals for contributors to keep in mind
main.go as simple as possiblecounterfeiter any more complicatedIf you have any questions about how to contribute, @joefitzgerald maintains counterfeiter and will work with you to make it better, together. This project has largely been maintained by the community, and we greatly appreciate any PR (whether big or small).
counterfeiter is MIT-licensed.
(top 24 of 27)
988 followers · starred Jan 2020
1,927 followers · starred May 2023
2,014 followers · starred Nov 2014
252 followers · starred Dec 2025