如何正确测试依赖项

时间:2018-12-08 22:10:27

标签: go testing dependency-injection

在Go中,我将如何测试以正确的方式调用了模拟依赖项。

如果我有一个采用依赖关系接口的结构,那么在注入后,我希望能够测试原始的模拟对象。

在此示例中,我当前的代码看不到struct值已更改。如果我将代码更改为通过引用传递,则会触发错误:

s.simpleInterface.Call不确定(类型* SimpleInterface是指向接口而不是接口的指针)

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")
    }
}

1 个答案:

答案 0 :(得分:3)

我看到三种简单的方法来解决此问题:

1-更改Call方法的签名以接收指向MockSimple的指针,并在实例化Simple结构时为其提供模拟地址:

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-不是最干净的解决方案,但仍然有效。如果您真的不能使用#1,请使用它。在其他地方声明“ hasBeenCalled”,然后更改您的MockSimple使其指向指针:

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-可能是一个非常糟糕的解决方案:使用全局变量,因此我只会将其用作最后的手段(始终避免使用全局状态)。将“ hasBeenCalled”设置为全局变量,然后从方法中对其进行修改。

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")
    }
}

干杯!