如何存根对 GitHub 的调用以进行测试?

我需要使用go-github创建一个拉取请求注释,我的代码可以工作,但现在我想为它编写测试(是的,我知道测试应该放在第一位),这样我就不会在测试期间实际调用真正的GitHub服务。

我已经阅读了3篇关于golang茬蛰和嘲笑的博客,但是,作为golang的新手,尽管对go-github问题进行了讨论,但我还是有点迷茫。例如,我编写了以下函数:

// this is my function

func GetClient(token string, url string) (*github.Client, context.Context, error) {

    ctx := context.Background()

    ts := oauth2.StaticTokenSource(

        &oauth2.Token{AccessToken: token},

    )

    tc := oauth2.NewClient(ctx, ts)

    client, err := github.NewEnterpriseClient(url, url, tc)


    if err != nil {

        fmt.Printf("error creating github client: %q", err)

        return nil, nil, err

    }

    return client, ctx, nil

}

我怎么能存根呢?


同样,我有这个:


func GetPRComments(ctx context.Context, client *github.Client) ([]*github.IssueComment, *github.Response, error)  {

    opts := &github.IssueListCommentsOptions{

        ListOptions: github.ListOptions{

            Page:    1,

            PerPage: 30,

        },

    }

    githubPrNumber, err := strconv.Atoi(os.Getenv("GITHUB_PR_NUMBER"))

    if err != nil || githubPrNumber == 0 {

      panic("error: GITHUB_PR_NUMBER is not numeric or empty")

    }


    // use Issues API for PR comments since GitHub docs say "This may seem counterintuitive... but a...Pull Request is just an Issue with code"

    comments, response, err := client.Issues.ListComments(

          ctx,

          os.Getenv("GITHUB_OWNER"),

          os.Getenv("GITHUB_REPO"),

          githubPrNumber,

          opts)

    if err != nil {

        return nil, nil, err

    }

    return comments, response, nil

}


我应该如何存根?


我的想法是也许通过首先创建自己的结构来使用依赖注入,但我不确定如何,所以目前我有这个:


func TestGetClient(t *testing.T) {

    client, ctx, err := GetClient(os.Getenv("GITHUB_TOKEN"), "https://example.com/api/v3/")

    c, r, err := GetPRComments(ctx, client)

    ...

}


小唯快跑啊
浏览 150回答 1
1回答

小怪兽爱吃肉

我会从一个界面开始:type ClientProvider interface {  GetClient(token string, url string) (*github.Client, context.Context, error)}测试需要调用的单元时,请确保依赖于接口:GetClientClientProviderfunc YourFunctionThatNeedsAClient(clientProvider ClientProvider) error {  // build you token and url  // get a github client  client, ctx, err := clientProvider.GetClient(token, url)    // do stuff with the client  return nil}现在,在您的测试中,您可以构造如下存根:// A mock/stub client provider, set the client func in your test to mock the behaviortype MockClientProvider struct {  GetClientFunc func(string, string) (*github.Client, context.Context, error)}// This will establish for the compiler that MockClientProvider can be used as the interface you createdfunc (provider *MockClientProvider) GetClient(token string, url string) (*github.Client, context.Context, error) {  return provider.GetClientFunc(token, url)}// Your unit testfunc TestYourFunctionThatNeedsAClient(t *testing.T) {  mockGetClientFunc := func(token string, url string) (*github.Client, context.Context, error) {    // do your setup here    return nil, nil, nil // return something better than this  }  mockClientProvider := &MockClientProvider{GetClientFunc: mockGetClientFunc}  // Run your test  err := YourFunctionThatNeedsAClient(mockClientProvider)  // Assert your result}这些想法不是我自己的,我从我之前的人那里借来的。Mat Ryer在一个关于“惯用语golang”的精彩视频中提出了这个(和其他想法)。如果要存根 github 客户端本身,可以使用类似的方法(如果是 github)。客户端是一个结构,你可以用一个接口来隐藏它。如果它已经是一个接口,则上述方法直接起作用。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go