Show HN: Moq – Easily mock interfaces in Go
Meet Moq: Easily mock interfaces in Go - Mat Ryer - Medium
Moq is an Interface mocking tool for go generate — github.com/matryer/moqIn 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) {    var sentTo string     // use the mocked object    mockedEmailSender = &EmailSenderMock{        SendFunc: func(to, subject, body string) error {            sentTo = to            return nil        },    }    CompleteSignUp("me@email.com", mockedEmailSender)    if len(mockedEmailSender.SendCalls()) != 1 {        t.Error("one 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 moqMoq is a simple tool that writes these structs for you. You can visit the project homepage at github.com/matryer/moq.How it worksAdd the go:generate comment above your interface:package storage//go:generate moq -out store_test.go . Storetype Store interface {    Get(id string) (interface{}, error)    Put(id string, v interface{}) error}The -out flag indicates where the output should be saved toThe dot (.) indicates that the interface lives in the current packageStore indicates that we want to mock the Store interfaceThen run go generate in a terminal and Moq will generate a new file called store_test.go containing something like this:package storagetype 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/moqAs usual, feedback and questions are welcome on Twitter @matryer.