Unit testing 测试和模拟不返回任何值的函数

Unit testing 测试和模拟不返回任何值的函数,unit-testing,go,mocking,gomock,Unit Testing,Go,Mocking,Gomock,我想测试一个函数,它不返回任何值,而是触发其他函数。在阅读有关测试的内容时,我发现了这样的信息:这称为行为验证,通过模拟,我可以检查触发了哪些函数以及触发的顺序。但是,我在为代码实现适当的模拟技术时遇到了一个问题 让我们考虑下面的接口和结构的一个简单例子(这个例子非常简单,以便解释起来): 现在,我想测试函数DoSomething。由于它不返回任何值,所以我想做的是测试在使用参数3调用此函数后,是否会发生以下事件链:使用参数6调用函数DoEvenMore一次,使用参数9调用下一个函数和evenm

我想测试一个函数,它不返回任何值,而是触发其他函数。在阅读有关测试的内容时,我发现了这样的信息:这称为行为验证,通过模拟,我可以检查触发了哪些函数以及触发的顺序。但是,我在为代码实现适当的模拟技术时遇到了一个问题

让我们考虑下面的接口和结构的一个简单例子(这个例子非常简单,以便解释起来):

现在,我想测试函数
DoSomething
。由于它不返回任何值,所以我想做的是测试在使用参数3调用此函数后,是否会发生以下事件链:使用参数
6
调用函数
DoEvenMore
一次,使用参数
9
调用下一个函数
和evenmore

我编写了以下模拟测试:

func TestDoSomething(t *testing.T) {

    mockCtrl := gomock.NewController(t)
    defer mockCtrl.Finish()

    mockClient := mocks.NewMockExampleInterface(mockCtrl)

    example := ExampleStruct("ExampleId")

    gomock.InOrder(
        mockClient.EXPECT().DoSomething(3).Return().Times(1)
        mockClient.EXPECT().DoEvenMore(6).Return().Times(1)
        mockClient.EXPECT().AndEvenMore(9).Return().Times(1) 
    )

    example.DoSomething(3)
}
然而,当我运行这个测试时,我得到了一个错误:
对*mocks.MockExampleInterface.DoSomething(…)
的意外调用


在这样的示例中,我应该如何正确地执行模拟?

DoSomething调用的两个方法都是具体的实现,您不能在Go中模拟类似的东西

要实现您想要的
DoSomething
必须依赖于定义这两个方法并调用它们而不是具体方法的接口

type DoMorer interface {
    DoEvenMore(arg int)
    AndEvenMore(arg int)
} 

type ExampleStruct struct {
     Id string 
     // Other fields
}

func (e *ExampleStruct) DoSomething(arg int, dm DoMorer) {
     arg2 := arg * 2
     dm.DoEvenMore(arg2)
     arg3 := arg * 3
     dm.AndEvenMore(arg3)  
}
通过这样的设置,在测试期间,您可以为
DoMorer
接口创建一个模拟,并将其传递给
DoSomething



DoMorer
不必作为参数传递给,它可以是
ExampleStruct
的字段,也可以是全局字段,只要符合您的需要。

哦,我现在明白了。谢谢!测试没有任何效果的东西的目的是什么?没有一个如果方法调用有影响,这里是副作用,请测试此副作用。这可能是对象的状态更改(易于观察)或环境中的状态更改(更难测试)。模仿通常是糟糕的测试计划和/或糟糕的设计的标志。
type DoMorer interface {
    DoEvenMore(arg int)
    AndEvenMore(arg int)
} 

type ExampleStruct struct {
     Id string 
     // Other fields
}

func (e *ExampleStruct) DoSomething(arg int, dm DoMorer) {
     arg2 := arg * 2
     dm.DoEvenMore(arg2)
     arg3 := arg * 3
     dm.AndEvenMore(arg3)  
}