unit-testing - 测试和模拟一个不返回任何值的函数

标签 unit-testing go mocking gomock

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

让我们考虑以下接口(interface)和结构的一个简单示例(该示例非常基础只是为了便于解释):

type ExampleInterface interface {
    DoSomething(arg int)
    DoEvenMore(arg int)
    AndEvenMore(arg int)
} 

type ExampleStruct struct {
     Id string 
     // Other fields
}

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

func (e *ExampleStruct) DoEvenMore(arg int){
     fmt.Println("I did so many operations here using ", arg)
}

func (e *ExampleStruct) AndEvenMore(arg int) {
     // Performing other operations on arg
}

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

我编写了以下模拟测试:

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

但是,当我运行此测试时,出现错误:Unexpected call to *mocks.MockExampleInterface.DoSomething(..) .

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

最佳答案

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

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

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 接口(interface)创建一个模拟并将其传递给 DoSomething


DoMorer 不必作为参数传递给它,它可以是 ExampleStruct 的字段或全局字段,只要满足您的需要即可。

关于unit-testing - 测试和模拟一个不返回任何值的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48082858/

相关文章:

java - PowerMock-IllegalStateException : Must replay Class XXX to get configured expectation

java - 为什么 null Mock 对象不会抛出 NullPointerException?

arrays - Unmarshal 只给我嵌套在 JSON 响应中的数组的第一个元素

testing - 包测试的串行执行

jquery - Protractor 模拟 jQuery ajax

javascript - stubbing process.exit 开 Jest

javascript - 调试模拟 httpbackend 请求

c# - 如何使用 FluentAssertions 断言集合按 2 个属性排序?

java - 在没有实例控制的情况下验证模拟类型的行为

mongodb - filter:= bson.D {{“hello”,“world”}}}而不是使用value(world)如何传递包含该值的变量(world)