Alberto Grespan

Introduction to HTTP testing in Go

— June 13, 2015

This post will be focused on a very basic introduction to HTTP testing in Go. Our goal will be to test a handler named helloHandler that responds with a custom header and a Hello World! body using only Go build-in Packages.

Creating the helloHandler

Creating our simple HTTP handler for our desired endpoint should be something like this:

// main.go
package main

import (
    "log"
    "net/http"
)

func helloHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("X-Hello-World-Type", "hello.v1")
    w.Write([]byte("Hello World!"))
}

func main() {
    http.HandleFunc("/", helloHandler)

    log.Fatal(http.ListenAndServe(":3000", nil))
}

Let’s see how our simple helloHandler works by using cURL on localhost:3000/:

% curl -i localhost:3000/
HTTP/1.1 200 OK
X-Hello-World-Type: hello.v1
Date: Mon, 08 Jun 2015 00:13:01 GMT
Content-Length: 12
Content-Type: text/plain; charset=utf-8

Hello World!%

Checking the response we see that it has a 200 status code, our custom header and the Hello World! body.

Now that we have our handler working we should go see how the tests for this looks like. The question is, what are we doing to test? Well… Those same things we just described, status code, header and body.

Tests to our handler

In my opinion there are four things we need to know before we start testing:

Overall it’s pretty straightforward, import all needed libraries, create a function for handler which name starts with “Test”, create a request and a recorder and pass those to the handler, do expectations using if statements.

Based on the above explanation our test for the main.go file should look something like this:

// main_test.go
package main

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

func TestHelloHandler(t *testing.T) {
    request, _ := http.NewRequest("GET", "/", nil)
    response := httptest.NewRecorder()

    helloHandler(response, request)

    if response.Code != http.StatusOK {
        t.Fatalf("Expected status code %v, but received: %v", "200", response.Code)
    }

    if response.Body.String() != "Hello World!" {
        t.Fatalf("Expected body: %v, but received: %v", "Hello World!", response.Body)
    }

    if response.Header().Get("X-Hello-World-Type") != "hello.v1" {
        t.Fatalf("Expected header: %v, but received: %v",
            "hello.v1", response.Header().Get("X-Hello-World-Type"))
    }
}

Our test file is called main_test.go we have a function that tests the helloHandler named TestHelloHandler that receives only a parameter and have three expectations. It should return 200, the body should be Hello World! and must contain our custom header.

If nothings wrong, running go test in our command line should look something like this:

go test
PASS
ok      github.com/albertogg/testest    0.006s

If one of our test fails the result looks like the following:

go test
--- FAIL: TestHelloHandler (0.00s)
        main_test.go:20: Expected body: Hello World!, but received: Hola Mundo!
FAIL
exit status 1
FAIL    github.com/albertogg/testest    0.006s

That’s all… Thanks for reading!