DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’» is a community of 966,904 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Create account Log in
NΓ­colas Barbosa
NΓ­colas Barbosa

Posted on

Testing HTTP handlers in Go

Introduction

In this example, I will create unit tests using the httptest library and we will see how to create test coverage for http handlers.

How to test http handlers in Go?

So we can test any handler http, we need a structure to be able to store the handler response, such as http status code, headers, body, etc.
The package httptest provide the structure httptest.ResponseRecorder, that's all we need to store the handler response.

// NewRecorder returns an initialized ResponseRecorder.
func NewRecorder() *ResponseRecorder {
    return &ResponseRecorder{
        HeaderMap: make(http.Header),
        Body:      new(bytes.Buffer),
        Code:      200,
    }
}
Enter fullscreen mode Exit fullscreen mode

The sample API

In our sample API, we have a handler called /check-is-prime, which checks if a number is prime.

The code:

The first test

The logic of the tests is very simple, for each test we build the HTTP request and then compare the response.

Adding more tests

Using table design in tests, its easy to add more cases:

{
    name: "must return http.StatusOk and true to prime number (7)",
    args: func(*testing.T) args {
        req, err := http.NewRequest("GET", "/check-is-prime", nil)
        if err != nil {
            t.Fatalf("fail to create request: %s", err.Error())
        }

        q := req.URL.Query()
        q.Add("number", "7")
        req.URL.RawQuery = q.Encode()

        return args{
            req: req,
        }
    },
    wantCode: http.StatusOK,
    wantBody: "true",
},
{
    name: "must return http.StatusOk and false because number (1) is not prime",
    args: func(*testing.T) args {
        req, err := http.NewRequest("GET", "/check-is-prime", nil)
        if err != nil {
            t.Fatalf("fail to create request: %s", err.Error())
        }

        q := req.URL.Query()
        q.Add("number", "1")
        req.URL.RawQuery = q.Encode()

        return args{
            req: req,
        }
    },
    wantCode: http.StatusOK,
    wantBody: "false",
},
Enter fullscreen mode Exit fullscreen mode

Complete code:

Conclusion

Have these utilities in the Go standard library, helps a lot when creating and maintaining our tests. We saw in practice with the package httptest.

Another important point is to isolate mux creation, this is necessary to call handlers in tests.

Top comments (0)

DEV has this feature:

Settings

Go to your customization settings to nudge your home feed to show content more relevant to your developer experience level. πŸ›