Skip to content
This repository has been archived by the owner on May 24, 2024. It is now read-only.
/ mockit Public archive

Library that make mocking of Go functions/methods easy

License

Notifications You must be signed in to change notification settings

pasdam/mockit

Repository files navigation

mockit

Go Report Card CI Status GoDoc

Mockit is a library to use during testing for Go application, and aim to make mocking of functions/methods easy.

Notes

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.

Usage

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.

Argument matcher

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.

Capture argument

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.

Pausing and restoring a mock

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()

Verify a call

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.

Update the library

To update the library to the latest version simply run:

go get -u github.com/pasdam/mockit

Development

TODOs

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):

Contributing

Rules to contribute to the repo:

  1. 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. in mockit.go for the mockit package.
  2. Write unit test for each method/function, in order to keep the coverage to 100%.

Internals

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.

Credits

All of this was possible only because of bouk, as this library is basically a wrapper around monkey, so kudos to him.