首页 > 解决方案 > 如何将此 api 提取到接口,以便在测试中模拟它?

问题描述

所以目前我有一个 http 处理程序,看起来像:

type App struct {

}
func (a *App) someHandler(w http.ResponseWriter, r *http.Request) {
        var api = slack.New("TOKEN")
        users = api.GetUsers()
}

我想为此 slack.New("...") 调用创建一个接口,以便在我的测试中,api 不会向 slack 发出网络请求。

我怎样才能模拟这个新的电话?

调用 New("TOKEN") 返回一个 *Client,见下面的链接:

func New(token string, options ...Option) *Client {
    s := &Client{
        token:      token,
        httpclient: &http.Client{},
        log:        log.New(os.Stderr, "nlopes/slack", log.LstdFlags|log.Lshortfile),
    }

    for _, opt := range options {
        opt(s)
    }

    return s
}

https://github.com/nlopes/slack/blob/0f8db5050731c50359e319cf253af5b9997a2b1e/slack.go#L84

我没有太多使用接口,所以不确定是否不能将其放入接口中,因为对 New 的调用就像一个构造函数?

标签: go

解决方案


您不能模拟slack.New调用本身,而是必须创建一个行为类似于此api对象的模拟。为此,将api放在App结构上,但作为接口:

type SlackClient interface {
    GetUsers() []string
}

type App struct {
    api SlackClient
}

func (a *App) someHandler(w http.ResponseWriter, r *http.Request) { 
    users = a.api.GetUsers() 
}

然后,您必须将调用移动slack.New到任何构造App(例如您的主函数或NewApp构造函数)中:

app = App{api: slack.New("TOKEN")}

此返回的 *Client 上有一个GetUsers方法,因此将匹配我们定义的接口。

然后测试用模拟做类似的事情:

type mockSlackClient struct {

}

func (m *mockSlackClient) GetUsers() []string {
    return nil
}

func TestSomeHandler(t *testing.T) {
    appToTest := App{api: &mockSlackClient{})

    appToTest.someHandler(httptest.NewRecorder(), nil)
}

同样,由于它上面*mockSlackClient有一个GetUsers方法,它将满足接口,因此您将能够在App.


推荐阅读