2017-06-14 13:22
浏览 86


I have two structs: FunctionalityClient and TestClient, both implementing Interface. I have a global variable Client of type Interface. I assign to Client either the actual client, or the mock client, depending on whether it's a test or a normal run.

Interface has a method Request that I want to mock in tests. That is, I want to:

  • record what were the argument passed to the function
  • return some arbitrarily defined return value from the function

So the struct looks like this:

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

And I use it like so:

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

Now the question.

I have a few structs that I want to mock like this. Currently I just copy and paste the code above for each struct. But that really sucks, I would like the mock logic to be abstracted away somehow. I would also accept something like Mockito's when: when the mocked function is called with specific arguments, return a specific value and record the call.

How can I properly mock a struct with member functions in Golang?

  • 写回答
  • 好问题 提建议
  • 追加酬金
  • 关注问题
  • 邀请回答

1条回答 默认 最新

相关推荐 更多相似问题