Mockit is a library to use during testing for Go application, and aim to make mocking of functions/methods easy.
This is still a working in progress so API might change before reaching a stable state.
Also please note that the mocking might not work in some cases if function inlining is enabled, so it might be necessary to disable it during testing:
go test -gcflags=-l
Finally this library currently supports amd64
platforms only, so ARM
ones
are not supported yet.
To mock a function:
m := MockFunc(t, filepath.Base)
m.With("some-argument").Return("result")
This will make sure that when filepath.Base
is called with the argument
some-argument
, it will return result
.
To mock an instance method (at the moment only exported methods are supported):
err := errors.New("some-error")
m := MockMethod(t, err, err.Error)
m.With().Return("some-other-value")
To mock a method for all the instances of a type:
err := errors.New("some-error")
m := MockMethodForAll(t, err, err.Error)
m.With().Return("some-other-value")
When a method is mocked and a matching call is not found (i.e. arguments are different) it will return the zero values.
It is possible to make the mock call the real method:
m.With("some-argument").CallRealMethod()
or return zero values:
m.With("some-argument").ReturnDefaults()
Mocks are matched in order, which means that:
m.With("some-argument").CallRealMethod()
m.With("some-argument").ReturnDefaults()
will make filepath.Base("some-argument")
call the real method.
Mocks are automatically removed when the test is completed.
It is also possible to use argument matchers, to implement generic behaviors. At the moment there is only one matcher implemented, and it matches any argument:
m := MockFunc(t, filepath.Base)
m.With(argument.any).Return("result")
This will make filepath.Base
return result
for any input.
To capture the argument of a call:
m := MockFunc(t, filepath.Base)
c := argument.Captor{}
m.With(c.Capture).Return("result")
filepath.Base("some-argument")
At this point c.Value
will be some argument
.
It is possible to temporary disable a mock:
m := MockFunc(t, filepath.Base)
m.With("matching-argument").Return("some-out")
// ... Do something with the mock
m.Disable()
At this point the mock is disabled and the real implementation is used.
To enable the mock again, just use:
m.Enable()
To verify a specified call happened:
m := MockFunc(t, filepath.Base)
// ... Mock calls
// ... And use mock
m.Verify("matching-argument")
The Verify
method will fail the test if the call didn't happen.
To update the library to the latest version simply run:
go get -u github.com/pasdam/mockit
This are (not in a particular order) the missing features that are going to be implemented in a not well defined future (patches are welcome):
- Mock unexported methods
- Mock interfaces
- Automatically verify at the end of the test, without having to call
verify
method - Verify in order calls
- Verifying exact number of invocations / at least x / never
- Arguments matcher
- IsA: to match for specific types
- NotNil: to match any not nil value
- Stubbing consecutive calls
- Stubbing with callbacks
- Mock variadic function
- Override existing mock, i.e. change return values of a stub
- Improve error messages
Rules to contribute to the repo:
- Define ine identifier per file, which means that each go file contains either
a struct (with related methods), an interface, or a function. Constants
should be declared in the file
<package>.go
, i.e. inmockit.go
for themockit
package. - Write unit test for each method/function, in order to keep the coverage to 100%.
This library uses monkey, a package for monkey patching in Go. And of course it inherits the same limitations, in particular:
Monkey sometimes fails to patch a function if inlining is enabled. Try running your tests with inlining disabled, for example: go test -gcflags=-l.
All of this was possible only because of bouk, as this library is basically a wrapper around monkey, so kudos to him.