Meet Moq: Easily mock interfaces in Go

Moq is an Interface mocking tool for go generate — github.com/matryer/moq

In my recent talk about Idiomatic Go Tricks I talked about a testing technique that David Hernandez showed me where you can test code that has dependencies (described by an interface) while keeping the mock code inside the test it belongs to.

You write a struct full of function fields that mirror the interface, and matching methods that just call those fields.

This allows you to write test code like this:

func TestCompleteSignup(t *testing.T) {

called := false
var sentTo string
    // use the mocked object
mockedEmailSender = &EmailSenderMock{
SendFunc: func(to, subject, body string) error {
called = true
sentTo = to
return nil
},
}

CompleteSignUp("me@email.com", mockedEmailSender)

if called == false {
t.Error("Sender.Send expected")
}
if sentTo != "me@email.com" {
t.Errorf("unexpected recipient: %s", sentTo)
}

}

func CompleteSignUp(to string, sender EmailSender) {
// TODO: this
}

You mock out the functions in EmailSenderMock that you expect to be called, and you can write throwaway custom behaviour for each specific test. You can see that the mocked functions are inside the test function itself, so it’s very clear to see what interactions with EmailSender we’re expecting when we call the CompleteSignUp method.

Inside the mocked functions, you can make assertions about what methods are being called, as well as decisions about what values to return. For example, you can decide to return an error, and make sure the code you are testing handles it properly.

The trouble with this technique is that there is a lot of boilerplate code to write each time you want to mock an interface. That’s where Moq comes in…

Introducing moq

Moq is a simple tool that writes these structs for you. You can visit the project homepage at github.com/matryer/moq.

How it works

Add the go:generate comment above your interface:

package storage
//go:generate moq -out store_test.go . Store
type Store interface {
Get(id string) (interface{}, error)
Put(id string, v interface{}) error
}
  • The -out flag indicates where the output should be saved to
  • The dot (.) indicates that the interface lives in the current package
  • Store indicates that we want to mock the Store interface

Then run go generate in a terminal and Moq will generate a new file called store_test.go containing something like this:

package storage
type StoreMock struct {
// GetFunc mocks the Get function.
GetFunc func(id string) (interface{}, error)
    // PutFunc mocks the Put function.
PutFunc func(id string, v interface{}) error
}
// Get calls GetFunc.
func (mock *StoreMock) Get(id string) (interface{}, error) {
return mock.GetFunc(id)
}
// Put calls PutFunc.
func (mock *StoreMock) Put(id string, v interface{}) error {
return mock.PutFunc(id, v)
}
This code is simplified — the actual generated code is slightly more sophisticated.

You can then use StoreMock instances in your test code wherever you test code that relies on a Store.

You can install Moq and use it today with:

go get github.com/matryer/moq

As usual, feedback and questions are welcome on Twitter @matryer.