Cookies management by TermsFeed Cookie Consent

๐Ÿงช Write end-to-end tests in Go using httptest.Server

shorts httptest http testing

Many programming languages, including Go, have frameworks for performing HTTP end-to-end (e2e) tests. However, not everyone knows that such tests can be performed using the httptest package built into the Go standard library. In this short article, we will show you how to do it - we will prepare end-to-end tests for a simple endpoint using only the httptest.Server from the httptest package.

End-to-end (e2e) testing is a type of software testing that aims to verify the functionality and behavior of an application from start to finish, simulating real-world scenarios.

In the case of an HTTP server, simulating real-world scenarios involves creating a test environment that is equivalent to the production environment, including the database, network and any other external dependencies. Once created, the test environment is used in e2e testing to send real HTTP requests with various parameters, headers and content. The corresponding HTTP responses from the server are verified by the tests to make sure everything works as intended, just as it would on a production environment.

HTTP handler for testing

Before we move on to testing, we need to create the web application that we will test. As the simplest example, we only need a single HTTP handler function such as HTTP Hello World:

hello_world.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
package main

import (
    "fmt"
    "net/http"
)

func HelloWorld(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "Hello World")
}

The only thing this handler does is to write the string “Hello World” in response to the HTTP request.

End-to-end test example

We will use httptest.Server to perform e2e tests. The httptest.Server is a structure built-in in Golang’s standard library (in the httptest package) that allows developers to create HTTP servers for testing purposes. This struct is useful when testing HTTP handlers, routers, and middlewares. It allows to test the operation of the application from start to finish locally, without setting up a separate testing environment on the remote host.

In the constructor, it accepts http.Handler as an input argument, so you can even use it to connect an entire application hidden behind a request router:

func NewServer(handler http.Handler) *httptest.Server

In our case, the handler will be our simple HelloWorld function converted using http.HandlerFunc().

We will perform end-to-end test in the standard hello_world_test.go file using the testing package. However, there is no problem to create a separate testing script working according to your own rules.

Take a look at our sample end-to-end test below:

hello_world_test.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package main

import (
    "io"
    "net/http"
    "net/http/httptest"
    "testing"
)

func TestHelloWorld(t *testing.T) {
    testServer := httptest.NewServer(http.HandlerFunc(HelloWorld))
    defer testServer.Close()
    testClient := testServer.Client()

    resp, err := testClient.Get(testServer.URL)
    if err != nil {
        t.Errorf("Get error: %v", err)
    }
    if resp.StatusCode != http.StatusOK {
        t.Errorf("response code is not 200: %d", resp.StatusCode)
    }
    data, err := io.ReadAll(resp.Body)
    if err != nil {
        t.Errorf("io.ReadAll error: %v", err)
    }
    if string(data) != "Hello World\n" {
        t.Error("response body does not equal to Hello World")
    }
}

So as you can see, testing web applications this way is very easy. All you need to do is to initialize httptest.Server, and then use it and its client to make HTTP requests, which you can then verify using test functions. The httptest.Server significantly simplifies the testing of HTTP applications and it is worth knowing this method when working with such applications on a daily basis.


Thank you for being on our site ๐Ÿ˜Š. If you like our tutorials and examples, please consider supporting us with a cup of coffee and we'll turn it into more great Go examples.

Have a great day!

Buy Me A Coffee

โฐ Handle HTTP timeout error in Go

shorts http

๐Ÿ”— Join URL path elements in Go

shorts net url path

๐Ÿ“ Convert date or time to string in Go

shorts introduction time