Simplify Testing by Embedding Interfaces

We can embed an interface inside a struct in Go.

I don’t remember what I was doing at the time—probably writing tests. Then, out of nowhere, I realized I could embed an interface inside a struct and implement only the methods I needed.

This is a neat little trick. I wonder why it isn't more widely used.

We embed the LargeExternalClient interface into mockClient, then implement only MethodF, because that’s the only method YourClient actually uses.

If somewhere in the code, some other method on the interface is in use without our knowledge and we forget to implement it on the mockClient, the test will panic. This is actually a good thing: we can add the missing method, and the test will fail loudly instead of silently passing.

package main

import (
        "testing"
)

// somewhere in the imported library.go

type LargeExternalClient interface {
        MethodA()
        MethodB()
        MethodC()
        MethodD()
        MethodE()
        MethodF() int
        MethodG()
        MethodH()
        MethodI()
}

// code.go
type YourClient struct {
        cli LargeExternalClient
}

func (y YourClient) Foo() int {
        return y.cli.MethodF()
}

// code_test.go

type mockClient struct {
        LargeExternalClient
}

func (mockClient) MethodF() int {
        return 23
}

func TestYourClient(t *testing.T) {
        y := YourClient{
                cli: new(mockClient),
        }

        if y.Foo() != 23 {
                t.Fail()
        }
}

You can try this example in the Go Playground, and read more about interface embedding at eli.thegreenplace.net.