programming

02 How to Used HTTP Test in Golang

Introduction to HTTP Testing

HTTP Test in Golang has been provided with a special package for creating unit tests for Web features. All of this is in the net/http/httptest package https://golang.org/pkg/net/http/httptest/. By using this package, we can unit test the web handler that we have created without having to run the web application so that we can immediately focus on the handler function that we want to test.

Methods in HTTP Test

  • httptest.NewRequest is a function used to create http.Request. We can determine the method, url, body that we will send as a unit test simulation. We can also add other additional information to the request we want to send, such as headers, cookies and so on.
  • httptest.NewRecorder() is the function used to create ResponseRecorder which is a help struct for recording the HTTP response from the results of the testing that we do.

How to implement HTTP Test

We are trying to create a handler that we can test, in the previous post we were able to create a HelloHandler which in this session we will add a unit test for that handler. The way to do this is to create a file in the learning-golang-web project and create the http_handler.go file.

package main

import (
	"fmt"
	"net/http"
)

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

If you use vscode then just open the file that we have created then hover our cursor over the function that we have created and right click select Go: Generate Unit Tests for function. Then a file http_handler_test.go will be created with contents like this.

package main

import (
	"net/http"
	"testing"
)

func TestHelloHandler(t *testing.T) {
	type args struct {
		w http.ResponseWriter
		r *http.Request
	}
	tests := []struct {
		name string
		args args
	}{
		// TODO: Add test cases.
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			HelloHandler(tt.args.w, tt.args.r)
		})
	}
}

Then we update the function and we will implement the httptest package to look like this.

func TestHelloHandler(t *testing.T) {
	tests := []struct {
		name string
		want string
	}{
		{
			name: "mencetak Hello World",
			want: "Hello World\n",
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			request := httptest.NewRequest(http.MethodGet, "http://localhost/hello", nil)
			recorder := httptest.NewRecorder()
			HelloHandler(recorder, request)

			response := recorder.Result()
			body, _ := io.ReadAll(response.Body)
			bodyString := string(body)

			if !reflect.DeepEqual(bodyString, tt.want) {
				t.Errorf("response = %v, want %v", bodyString, tt.want)
			}
		})
	}
}

When we run the unit test with the command below

go test

then the result if it is appropriate will produce something like this

➜  learn-golang-web git:(main) ✗ go test                                  
PASS
ok      github.com/santekno/learn-golang-web  0.984s
comments powered by Disqus