2017-06-14 86 views
0

我有两个结构:FunctionalityClientTestClient,都执行Interface。我有一个类型Interface的全局变量Client。我将Client分配给实际客户端或模拟客户端,具体取决于它是测试还是正常运行。如何在Golang中使用成员函数正确地模拟结构?

Interface有一个方法Request,我想模拟测试。也就是说,我想:

  • 记录什么是传递给函数的
  • 返回参数从功能

一些任意定义的返回值,因此结构是这样的:

type TestClient struct { 
    recordedArgs []interface{} 
    returnValues []interface{} 
} 
func (c *TestClient) Request(body io.Reader, method string, endpoint string, headers []Header) ([]byte, error) { 
    c.recordedArgs = append(c.recordedArgs, []interface{}{body, method, endpoint, headers}) // this can't be typed if I want the code to be reusable 
     if len(c.returnValues) != 0 { 
     last := c.returnValues[0] 
     c.returnValues = c.returnValues[1:] 
     return last.([]byte), nil 
    } 
    return nil, nil 
} 

我用它像这样:

testClient := TestClient{ 
    returnValues: []interface{}{ 
     []byte("arbitrarily defined return value"), 
     []byte("this will be returned after calling Request a second time"), 
    } 
} 
Client = &testClient 
// run the test 
// now let's check the results 
r1 := testClient.recordedArgs[1].([]interface{}) // because I append untyped lists to recordedArgs 
assert.Equal(t, "POST", r1[1].(string)) 
assert.Equal(t, "/file", r1[2].(string)) 
// and so on 

现在的问题。

我有几个结构,我想嘲笑这样的。目前我只是复制并粘贴上面的代码为每个结构。但这真的很糟糕,我希望模拟逻辑能够以某种方式被抽象出来。我也会接受像Mockito的when这样的东西:当使用特定参数调用模拟函数时,返回一个特定值并记录调用。

我怎样才能正确地模拟一个结构与Golang中的成员函数?

+0

因为您知道每个元素都将是[] interface {},所以您可以通过设置recordedArgs a [] [] interface {}来简化这一点。它为您节省了一些不必要的类型断言。 – Adrian

回答

0

如果您正在模拟客户端使用HTTP API,您可能只需要使用httptest.Server,这可以极大地简化这个过程。而不是嘲笑客户端,嘲笑客户端连接的服务器。它非常易于使用,并且您仍然可以记录请求方法,路径,主体等,以及以与模拟客户端相同的方式返回任意响应值。

如果这不是一个选项,你可以抽象出你的模拟方法,以使其可重复使用:

type TestClient struct { 
    recordedArgs [][]interface{} 
    returnValues []interface{} 
} 

func (c *TestClient) mock(args ...interface{}) interface{} { 
    c.recordedArgs = append(c.recordedArgs, args) 
    if len(c.returnValues) != 0 { 
     last := c.returnValues[0] 
     c.returnValues = c.returnValues[1:] 
     return last 
    } 
    return nil 
} 

func (c *TestClient) Request(body io.Reader, method string, endpoint string, headers []Header) ([]byte, error) { 
    return c.mock(body,method,endpoint,headers).([]byte), nil 
} 

这样可以减少您的具体使用情况的方法下到一线。

相关问题