Skip to content
This repository was archived by the owner on Oct 21, 2025. It is now read-only.

Collection of mocks for use with GitLab Golang SDK (github.com/xanzy/go-gitlab)

License

Notifications You must be signed in to change notification settings

rumenvasilev/go-gitlab-mock

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

go-gitlab-mock

Go Reference Go Report Card Build

THIS LIBRARY IS NO LONGER NEEDED, GITLAB HAVE PUBLISHED THEIR OWN https://gitlab.com/gitlab-org/api/client-go/-/tree/main/testing

A library to aid unit testing Go code that uses Gitlab SDK (currently based on github.com/xanzy/go-gitlab)

I've copied (and adapted) the code generation and mock structure from github.com/migueleliasweb/go-github-mock. That is reflected in the LICENSE as well. To get to the current state though, I had to build GitLab's OpenAPI spec. It is not available on the internet (at least I couldn't find a near-complete spec), which is why I have generated it off their source code and then used it for the mocks.

Installation

go get github.com/rumenvasilev/go-gitlab-mock

Features

  • Create mocks for successive calls for the same endpoint
  • Pagination support
  • Mock error returns
  • High level abstraction helps writing readabe unittests (see mock.WithRequestMatch)
  • Lower level abstraction for advanced uses (see mock.WithRequestMatchHandler)

Example

import "github.com/rumenvasilev/go-gitlab-mock/mock"

Multiple requests

mockedURL := NewMockedHTTPServer(
    WithRequestMatch(
        GetApiV4UsersById,
        &gitlab.User{
            ID:   5,
            Name: "foobar",
        },
    ),
    WithRequestMatch(
        GetApiV4Groups,
        []*gitlab.Group{
            {
                Name: "foobar123thisorgwasmocked",
            },
        },
    ),
    WithRequestMatchHandler(
        GetApiV4Projects,
        http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
            w.Write(MustMarshal([]gitlab.Project{
                {
                    Name: "mocked-proj-1",
                },
                {
                    Name: "mocked-proj-2",
                },
            }))
        }),
    ),
)

c, err := gitlab.NewClient("", gitlab.WithBaseURL(mockedURL))

user, _, userErr := c.Users.GetUser(1, gitlab.GetUsersOptions{})

// user.Name == "foobar"

groups, _, groupsErr := c.Groups.ListGroups(&gitlab.ListGroupsOptions{})

// groups[0].Name == "foobar123thisorgwasmocked"

projs, _, projsErr := c.Projects.ListProjects(&gitlab.ListProjectsOptions{})

// projs[0].Name == "mocked-proj-1"
// projs[1].Name == "mocked-proj-2"

Returning empty results

mockedURL := NewMockedHTTPServer(
    WithRequestMatch(
        GetApiV4ProjectsIssuesById,
        []*gitlab.Issue{
            {
                ID:    123,
                Title: "Issue 1",
            },
            {
                ID:    456,
                Title: "Issue 2",
            },
        },
        []*gitlab.Issue{},
    ),
)
c, err := gitlab.NewClient("", gitlab.WithBaseURL(mockedURL))

issues1, _, issues1Err := c.Issues.ListProjectIssues(1, &gitlab.ListProjectIssuesOptions{})

// len(issues1) == 2
// issues1Err == nil

issues2, _, issues2Err := c.Issues.ListProjectIssues(2, &gitlab.ListProjectIssuesOptions{})

// len(issues2) == 0
// issues2Err == nil

Mocking errors from the API

mockedURL := NewMockedHTTPServer(
    WithRequestMatchHandler(
        GetApiV4UsersById,
        http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            WriteError(
                w,
                http.StatusInternalServerError,
                "test error we've defined",
            )
        }),
    ),
)

c, err := gitlab.NewClient(
    "",
    gitlab.WithBaseURL(mockedURL),
    gitlab.WithCustomBackoff(
        func(_, _ time.Duration, _ int, _ *http.Response) time.Duration { return 0 }
    )
) // use timeout 0, so we can get the response immediately

user, _, userErr := c.Users.GetUser(1, gitlab.GetUsersOptions{})

// user == nil

if userErr == nil {	
    if glErr, ok := userErr.(*gitlab.ErrorResponse); ok {
        fmt.Println(glErr.Message) // == "test error we've defined"
    }
}

Mocking with pagination

mockedURL := NewMockedHTTPServer(
    WithRequestMatchPages(
        GetApiV4GroupsProjectsById,
        []*gitlab.Project{
            {
                Name: "repo-A-on-first-page",
            },
            {
                Name: "repo-B-on-first-page",
            },
        },
        []*gitlab.Project{
            {
                Name: "repo-C-on-second-page",
            },
            {
                Name: "repo-D-on-second-page",
            },
        },
    ),
)

is := is.New(t)
c, err := gitlab.NewClient(
    "",
    gitlab.WithBaseURL(mockedURL),
    gitlab.WithCustomBackoff(
        func(_, _ time.Duration, _ int, _ *http.Response) time.Duration { return 0 }
    )
)
is.NoErr(err)

opt := &gitlab.ListGroupProjectsOptions{
    ListOptions: gitlab.ListOptions{
        // in fact, the perPage option is ignored
        // but this would be present in production code
        PerPage: 2,
    },
}

var allProjs []*gitlab.Project

for {
    projs, resp, listErr := c.Groups.ListGroupProjects(1, opt)
    is.NoErr(listErr)
    is.Equal(len(projs), 2)

    allProjs = append(allProjs, projs...)

    if resp.NextPage == 0 {
        break
    }

    opt.Page = resp.NextPage
}

// matches the mock definitions len(page[0]) + len(page[1])
// len(allRepos) == 4

Why

I was working on a project that was using GitLab's REST API. And I wanted to write tests for that. And I couldn't. Until now.

Thanks

Thanks to @migueleliasweb for his go-github-mock project that was the baseline for this one.

License

This library is distributed under the MIT License found in LICENSE.

About

Collection of mocks for use with GitLab Golang SDK (github.com/xanzy/go-gitlab)

Topics

Resources

License

Stars

Watchers

Forks

Languages