drnycqxwz63508434
2018-01-03 18:08
浏览 48
已采纳

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

I want to test a function, which does not return any value, but instead triggers other functions. While reading about testing, I found information that this is called a behavioral verification and that by mocking I can check what functions and in what order are triggered. However, I have a problem to implement the proper mocking technique for my code.

Let's consider a simple example of the following interface and struct (the example is very basic just to make it easier to explain):

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
}

Now, I want to test function DoSomething. Since it does not return any value what I want to do is to test whether after calling this function with argument 3 the following chain of events happens: function DoEvenMore is called once with argument 6, and next function AndEvenMore is called once with argument 9

I wrote the following mocking test:

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

However, when I run this test I get the error: Unexpected call to *mocks.MockExampleInterface.DoSomething(..).

How I should properly perform the mocking in such example?

图片转代码服务由CSDN问答提供 功能建议

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

让我们考虑以下接口和结构的简单示例(该示例非常基本,只是为了使其易于解释):

  type ExampleInterface接口{
 DoSomething(arg int)
 DoEvenMore(arg int)
 AndEvenMore(arg int)
} 
 
type ExampleStruct struct {
 ID string 
 //其他字段
} \  n 
func(e * ExampleStruct)DoSomething(arg int){
 arg2:= arg * 2 
 e.DoEvenMore(arg2)
 arg3:= arg * 3 
 e.AndEvenMore(arg3)
} \  n 
func(e * ExampleStruct)DoEvenMore(arg int){
 fmt.Println(“我在这里使用”,arg)做了很多操作
} 
 
func(e * ExampleStruct)AndEvenMore(arg int){  
 //在arg 
} 
   
 
 

上执行其他操作现在,我想测试函数 DoSomething 。 由于它不返回任何值,因此我想测试在使用参数3调用此函数后是否发生以下事件链:函数 DoEvenMore 用参数 6调用一次。 code>,然后使用参数 9

调用一次下一个函数 AndEvenMore ,我编写了以下模拟测试: \ n

  func TestDoSomething(t * testing.T){
 
模拟Ctrl:= gomock.NewController(t)
延迟模拟Ctrl.Finish()
 
模拟客户端:=模拟.NewMockExampleInterface  (mockCtrl)
 
示例:= ExampleStruct(“ ExampleId”)
 
 gomock.InOrder(
 mockClient.EXPECT()。DoSomething(3).Return()。Times(1)
模拟客户端.EXPECT  ().DoEvenMore(6).Return()。Times(1)
模拟客户端.EXPECT()。AndEvenMore(9).Return()。Times(1)
)
 
示例.DoSomething(3)  
} 
   
 
 

但是,当我运行此测试时,出现错误:意外调用* mocks.MockExampleInterface.DoSomething(..)

在这样的示例中如何正确执行模拟?

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • dongmouhao7438 2018-01-03 19:43
    已采纳

    The two methods called by DoSomething are concrete implementations, you cannot mock something like that in Go.

    To achieve what you want DoSomething would have to depend on an interface that defines those two methods and call those instead of the concrete ones.

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

    With a setup like this, during testing, you can create a mock for the DoMorer interface and pass that to DoSomething.


    DoMorer doesn't have to be passed to as an argument, it could be a field of ExampleStruct or a global, whatever suits your needs.

    已采纳该答案
    打赏 评论

相关推荐 更多相似问题