如何在具有接口的API客户端中嵌套端点,同时保持可读性 [英] How to nest endpoints in a API client with interfaces while keeping readability

查看:96
本文介绍了如何在具有接口的API客户端中嵌套端点,同时保持可读性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图组成一个简单的API客户端,但我一直试图弄清楚如何使其变得可读和可测试.如何在保持可测试性的同时组成嵌套结构?

I'm trying to compose a simple API client I'm stuck trying to figure out how to make it readable and testable. How can I compose a nested structure while keeping it testable?

伪代码:

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了:

Now I can call API like so:

api.Vehicle.Car.Get(kind)

这为我提供了一个非常易读(嵌套)的实现,但是我很难模拟这些端点,因为使用接口会有效地消除对嵌套结构的任何识别. 推荐的构造API的方法是使它在保持端点可读性的同时又模拟每个端点?

This gives me a very readable (nested) implementation to work with however I'm having a hard time mocking these endpoints because the use of interface would effectively remove any recognition of the nested structure. What would be the recommended way to construct an API keeping it very readable while also having each endpoint mocked?

推荐答案

您正在与语言作斗争,并将您的OOP爱好带入并非为此设计的语言.

You are fighting with language and bringing your OOP hobbies into language that is not designed for that.

我个人会改变方向,并使用老式的良好平面结构和功能.

I personally would change direction and use old good flat structures and functions.

尽管,如果您想继续进行设计,则可以模拟不是接口而是整个http堆栈.在测试实际的http有效负载而不是对接口进行调用时,可以更加自信地测试代码.

Although, if you want to continue with your design, you can mock not interface but whole http stack. You can test your code with much better confidence as you testing real http payload vs making calls to your interfaces.

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客户端:

Create Http Client from mux server:

client := server.Client()

这篇关于如何在具有接口的API客户端中嵌套端点,同时保持可读性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆