我试图编写一个简单的API客户端,但我一直试图弄清楚如何使其变得可读和可测试。如何在保持可测试性的同时组成嵌套结构?
伪代码:
type VehicleEndpoint struct {
Car CarEndpoint
VehicleGetter
}
type VehicleGetter interface {
Get(string) Vehicle
}
type Vehicle struct {
kind string
}
type VehicleClient struct {
http.Client
url string
}
func (v *VehicleClient) Get(kind string) Vehicle {
resp := v.Do(v.url, kind)
return Vehicle{
kind: resp.Kind
}
}
type CarEndpoint struct
...
type CarGetter interface
...
type Car struct
...
type CarClient struct
...
type API struct {
Vehicle VehicleEndpoint
}
api := API{
Vehicle: VehicleEndpoint{
VehicleGetter: VehicleClient{
http.Client{},
}
Car: CarEndpoint{
CarGetter: CarClient{
http.Client{},
}
}
}
}
现在,我可以像这样调用API:
api.Vehicle.Car.Get(kind)
这为我提供了一个非常易读(嵌套)的实现,但是我很难模拟这些端点,因为使用接口会有效地消除对嵌套结构的任何识别。 推荐一种构造API的方法,以保持其可读性,同时模拟每个端点?
答案 0 :(得分:3)
您正在与语言作斗争,并将您的OOP爱好带入并非为此设计的语言。
我个人会改变方向,并使用老式的良好平面结构和功能。
尽管,如果您想继续进行设计,则可以模拟整个接口http
,而不模拟接口。在测试实际的http
有效负载而不是对接口进行调用时,您可以更加自信地测试代码。
将HttpClient
注入Vehicle
:func NewVehicle(httpClient *http.Client){}
在测试代码中,使用*http.ServeMux
:
mux.Handle("/path1", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// assessments and mocked response
}))
mux.Handle("/path2", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// assessments and mocked response
}))
// fallback to show not implemented routes
result.mux.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
result.t.Errorf("Not Supported route %q", r.URL.Path)
}))
构建Http服务器:
server := httptest.NewServer(mux)
从多路复用器服务器创建Http客户端:
client := server.Client()