unit-testing - 在测试中覆盖 Go 方法

标签 unit-testing oop testing go

所以我有这个 Client 结构,它有一个方法 UserByID,它向 User 的端点发出 HTTP 请求。我想对该函数进行单元测试,但也不想在函数 c.Request 中发出实际的 HTTP 请求。我想用我可以控制的响应和错误来 stub 该函数。

func (c Client) UserByID(id string) (u User, err error) {
  v := url.Values{}
  v.Set("id", id)
  opts := Request{
    HTTP: http.Request{
        Method: http.MethodGet,
        Form:   v,
    },
    URL: 'some/endpoint/users',
  }
  resp, err := c.Request(opts)
  err = json.Unmarshal(resp, &u)
  return
}

这是 stub 的样子:

type mockClient struct {
  Client
  fakeUser  User
  fakeError error
}

func (mc mockClient) Request(opts Request) (resp []byte, err error) {
  resp, err = json.Marshal(mc.fakeUser)
  err = mc.fakeError
  return
}

在一次测试中我有类似的东西:

client := mockClient{
  fakeUser: User{},
  fakeError: nil,
}
user, err := client.UserByID(c.id)

然后我可以断言 client.UserByID 的返回值。在这个例子中,我试图覆盖 client.Request 函数,但我知道 Go 不是一种继承类型的语言。在我的测试中,我的 mockClient.Request 函数没有被调用。原来的client.Request还在被调用。

然后我假设我的方法不对。如何测试 client.UserByID 而不实际调用其中的真正的 client.Request 函数?我的方法设计是否应该有所不同?

最佳答案

为了完成您的需要,您可以稍微重构一下代码。

您可以在此处找到完整的工作示例:https://play.golang.org/p/VoO4M4U0YcA

下面是解释。

首先,在你的包中声明一个变量函数来封装 HTTP 请求的实际制作:

var MakeRequest = func(opts Request) (resp []byte, err error) {
    // make the request, return response and error, etc
}

然后,在您的 Client 中使用该函数发出请求:

func (c Client) Request(opts Request) (resp []byte, err error) {
    return MakeRequest(opts)
}

这样,当你实际使用客户端时,它会按预期发出 HTTP 请求。

但是当您需要测试时,您可以为该 MakeRequest 函数分配一个模拟函数,以便您可以控制它的行为:

// define a mock requester for your test

type mockRequester struct {
    fakeUser  User
    fakeError error
}

func (mc mockRequester) Request(opts Request) (resp []byte, err error) {
    resp, err = json.Marshal(mc.fakeUser)
    err = mc.fakeError
    return
}

// to use it, you can just point `MakeRequest` to the mock object function

mockRequester := mockRequester{
    fakeUser:  User{ ID: "fake" },
    fakeError: nil,
}
MakeRequest = mockRequester.Request

关于unit-testing - 在测试中覆盖 Go 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50544943/

相关文章:

java - 如何使用 Mockito 实现复合对象

testing - 在生产中运行端到端测试是否值得?

android - 从测试人员的安卓设备获取 logcat

matlab - 在 Matlab 中的父类(super class)上定义自定义方法和属性 block

javascript - 如何让 node.js 和 Mocha 在浏览器中运行(测试)?

unit-testing - 在 golang 中实现嵌套接口(interface)

unit-testing - 为编译器阶段编写可维护的测试

java - 如何使用 Mockito 在另一个 Mock 类中模拟 Spring 消息资源?

javascript - 如何将正则表达式分配给变量以供以后在字符串上使用?

c++ - 在类中使用全局函数