1

我正在尝试编写一个简单的 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 的推荐方法是什么,既要保持可读性,又要模拟每个端点?

4

1 回答 1

3

您正在与语言作斗争,并将您的 OOP 爱好带入不是为此而设计的语言。

我个人会改变方向并使用旧的良好平面结构和功能。

虽然,如果你想继续你的设计,你可以模拟的不是界面而是整个http堆栈。http当您测试真正的有效负载而不是调用您的接口时,您可以更有信心地测试您的代码。

注入:HttpClient_Vehiclefunc 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()
于 2018-11-09T19:11:36.057 回答