【发布时间】:2018-11-05 18:46:57
【问题描述】:
所以我有这个Client 结构,它有一个方法UserByID,它向User 的端点发出HTTP 请求。我想对该函数进行单元测试,但也不想在函数c.Request 中发出实际的 HTTP 请求。我想用我可以控制的响应和错误来存根该函数。
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
}
这是存根的样子:
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 函数?我的方法的设计应该不同吗?
【问题讨论】:
-
不要模拟你的方法——模拟你的方法调用的函数。所以在这种情况下,模拟
c.Request()--或模拟它与之对话的服务器(在 Go 中启动一个可以发送实际 HTTP 响应供您的测试使用的测试服务器是微不足道的)。 -
Java 式的单元测试尝试在 Go 中注定要失败。不要这样做。要么调用一个实际的 HTTP 服务器(微不足道的),要么分离这个功能。甚至永远不要在 Go 中尝试传统的 OOP 技术,它们都会失败。
标签: unit-testing oop testing go