Yet another tool to mock interfaces in Go

As a powerful tool, unit tests can give the ability to check every aspect of the code behavior. If you keep in mind an idea about the need for code testing, you will always write sustainable and maintainable code. Well designed code that depends on abstractions is easy to test, so code testability also can serve as an indicator of its quality.
If you have already tried to test code in Go, you probably know how useful interfaces can be. Go standard library provides you with a bunch of interfaces that you’re able to use in your code and most of them contain just a single method.
Go also has a supplementary framework created to help mock interfaces and a bunch of other community-driven packages that share similar functionality. Most of them give the ability to generate a struct that implements a given interface; this is very useful if an interface is large or it embeds other interfaces. But isn’t it too much when an interface has a single method?
The most amazing part about interfaces in Go is that they’re satisfied implicitly. Any type satisfies an interface simply by providing methods whose signature matches the interface declaration. This type could be even a function and if you’re familiar with the package net/http
you might have already seen one of these types also called adapters
.
As you can see, adapter
itself is a function type with the same signature as the interface method declaration and it implements an interface by calling itself in the corresponding method. This adapter
allows implementing Handler
by any function with the appropriate signature. It comes as a generic tool to mock interfaces and looks very handy in table driven tests. For example, here’s the code that should be tested:
With the usage of the adapter
, unit tests might look something like this:
Writing such adapters
can be really annoying, so I’ve decided to write a tool for their automatic generation and called it adapt, this tool generates an adapter
for a specified interface and prints it in the output. All you need is to pass a package name and an interface name to generate it.
$ adapt io Reader
type readerFunc func([]byte) (int, error)
func (f readerFunc) Read(p []byte) (int, error) {
return f(p)
}
You also can call adapt
inside a package folder to generate an adapter for some of the package interfaces.
$ cd $GOPATH/src/github.com/x/execute Doer
$ adapt Doer
type doerFunc func() (int, error)
func (f doerFunc) Do() (int, error) {
return f()
}
It comes with a handy vim plugin which gives an ability to generate anadapter
inside the vim.

Hopefully, you will find it useful.