如何正确测试依赖项

In Go, how would I test that a mock dependency has been called in the correct way.

If I have a struct that takes a interface for a dependency, after injection I want to be able to test the original mock object has been called.

My current code in this example I can not see that the struct value has changed. If I change my code to pass by reference it triggers the error:

s.simpleInterface.Call undefined (type *SimpleInterface is pointer to interface, not interface)

type SimpleInterface interface {
    Call()
}

type Simple struct {
    simpleInterface SimpleInterface
}

func (s Simple) CallInterface() {
    s.simpleInterface.Call()
}

type MockSimple struct {
    hasBeenCalled bool
}

func (ms MockSimple) Call() {
    ms.hasBeenCalled = true
}

func TestMockCalled(t *testing.T) {
    ms := MockSimple{}
    s := Simple{
        simpleInterface: ms,
    }
    s.CallInterface()

    if ms.hasBeenCalled != true {
        t.Error("Interface has not been called")
    }
}

I see three easy ways to fix this:

1- Change the signature of the Call method to receive a pointer to MockSimple, and when instantiating the Simple struct, give it the address of your mock:

func (ms *MockSimple) Call() {
    ms.hasBeenCalled = true
}

func TestMockCalled(t *testing.T) {
    ms := MockSimple{}
    s := Simple{
        simpleInterface: &ms,
    }
    s.CallInterface()

    if ms.hasBeenCalled != true {
        t.Error("Interface has not been called")
    }
}

2- Not the cleanest solution, but still works. Use it if you really cant use #1. Declare "hasBeenCalled" somewhere else and change your MockSimple to hold a pointer to it:

type MockSimple struct {
    hasBeenCalled *bool
}

func (ms MockSimple) Call() {
    *ms.hasBeenCalled = true
}

func TestMockCalled(t *testing.T) {
    hasBeenCalled := false
    ms := MockSimple{&hasBeenCalled}
    s := Simple{
        simpleInterface: ms,
    }
    s.CallInterface()

    if hasBeenCalled != true {
        t.Error("Interface has not been called")
    }
}

3- Probably a really bad solution: using globals, so I would only use it as a last resort (always avoid global state). Make "hasBeenCalled" a global and modify it from the method.

var hasBeenCalled bool

type MockSimple struct{}

func (ms MockSimple) Call() {
    hasBeenCalled = true
}

func TestMockCalled(t *testing.T) {
    ms := MockSimple{}
    s := Simple{
        simpleInterface: ms,
    }
    s.CallInterface()

    if hasBeenCalled != true {
        t.Error("Interface has not been called")
    }
}

Cheers!