Creating a Test HTTP Server in Go

muaazsaleem

Muaaz Saleem

Posted on January 17, 2021

Creating a Test HTTP Server in Go

httptest.NewServer gives us the ability to spin up a local HTTP Server. This is very useful say, when testing an HTTP client.

Usage

Here's a very basic usage of httptest.NewServer:

server := httptest.NewServer(
        http.HandlerFunc(
            func(w http.ResponseWriter, req *http.Request) {
            _, _ = fmt.Fprint(w, "OK")
        }))
    defer server.Close()
Enter fullscreen mode Exit fullscreen mode

In the code above, server.URL can be used to connect to the server. For example, we could pass it to the following pingService func to test it.

func pingService(url string) ServiceStatus {
    // TODO: make sure url is actually a valid URL
    res, err := http.Get(url)
    // expecting the HTTP client to err out if the service is down
    if err != nil {
        // TODO: add TestURL to the log
        log.Errorf("[%s], is DOWN", url)
        return ServiceDown
    }
}
Enter fullscreen mode Exit fullscreen mode

A more complete example

Following is a more complete example of pingService and its tests:

pingService()

// ServiceStatus indicates the status of a service i.e "UP", "FAILING", "DOWN"
type ServiceStatus string

const (
    ServiceUP      = ServiceStatus("UP")
    ServiceDown    = ServiceStatus("DOWN")
    ServiceFailing = ServiceStatus("FAILING")
)

func pingService(server *http.Server) ServiceStatus {
    // TODO: make sure server.URL is actually a valid URL
    res, err := http.Get(server.URL)
    // expecting the HTTP client to err out if the service is down
    if err != nil {
        // TODO: add TestURL to the log
        log.Errorf("[%s], is DOWN", server.URL)
        return ServiceDown
    }

    if res.StatusCode >= 200 && res.StatusCode <= 500 {
        log.Infof("[%s], is UP", server.URL)
        return ServiceUP
    } else {
        log.Errorf("[%s], is FAILING", server.URL)
        return ServiceFailing
    }
}
Enter fullscreen mode Exit fullscreen mode

Testing pingService()

// TestStatusDown tests pinging a non running HTTP service
func TestStatusDown(t *testing.T) {
    ss := pingService(exampleTestService)
    require.Equal(t, ServiceDown, ss)
}

// TestStatusUP tests a running HTTP service
func TestStatusUP(t *testing.T) {
    sv := httptest.NewServer(
        http.HandlerFunc(
            func(w http.ResponseWriter, req *http.Request) {
            _, _ = fmt.Fprint(w, "OK")
        }))
    defer sv.Close()

    ss := pingService(sv)
    require.Equal(t, ServiceUP, ss)
}

// TestStatusFailing tests a failing HTTP service
func TestStatusFailing(t *testing.T) {
    sv := httptest.NewServer(
        http.HandlerFunc(
            func(w http.ResponseWriter, req *http.Request) {
            w.WriteHeader(http.StatusInternalServerError)
        }))
    defer sv.Close()

    ss := pingService(sv)
    require.Equal(t, ServiceFailing, ss)
}
Enter fullscreen mode Exit fullscreen mode

Further Resources:

💖 💪 🙅 🚩
muaazsaleem
Muaaz Saleem

Posted on January 17, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related