我试图组成一个简单的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的方法,以保持其可读性,同时模拟每个端点?
您正在与语言作斗争,并将您的OOP爱好带入并非为此设计的语言。
我个人会改变方向,并使用老式的良好平面结构和功能。
虽然,如果您想继续进行设计,则可以模拟整个接口而不是接口http。在测试实际http有效负载而不是对接口进行调用时,可以更加自信地测试代码。
http
注入HttpClient到Vehicle:func NewVehicle(httpClient *http.Client){}
HttpClient
Vehicle
func NewVehicle(httpClient *http.Client){}
在测试代码中,使用*http.ServeMux:
*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()