A handler test example

A handler test example

A simple example on how to test a handler.

A simple server

First we create a simple server, where we create a simple mux router which handles a single endpoint by the name /hello. This handler is simply gonna return “Hello world!”.

Ourmain.go file can look something like this:

func main() {
  mux := handlers()

  mux.HandleFunc("/hello", helloHandler)

  server := http.Server{
    Addr:         ":8080",
    WriteTimeout: 10 * time.Second,
    ReadTimeout:  10 * time.Second,
    Handler:      mux,
  }

  log.Println("Listening at port:", server.Addr)
  log.Fatal(server.ListenAndServe())
}

Our handlers looks like this:

func handlers() *http.ServeMux {
  router := http.NewServeMux()

  router.HandleFunc("/hello", helloHandler)

  return router
}

And then our helloHandler which is going to return “Hello world!”:

func helloHandler(w http.ResponseWriter, r *http.Request) {
  fmt.Fprint(w, "Hello world!")
}

Now we have a simple server that returns “Hello world!” on /hello.

Simple test

Testfile main_test.go can look like this:

func Test_handlers(t *testing.T) {
  type args struct {
    query  string
    method string
  }
  tests := []struct {
    name string
    want string
    args args
  }{
    {
      name: "hello handler",
      want: "Hello world!",
      args: args{
        query:  "/hello",
        method: http.MethodGet,
      },
    },
  }

    handler := handlers()
    resp := httptest.NewRecorder()
    for _, tt := range tests {
      t.Run(tt.name, func(t *testing.T) {
        req, err := http.NewRequest(tt.args.method, tt.args.query, nil)
        if err != nil {
          t.Errorf("handlers() err: %v", err)
        }

        handler.ServeHTTP(resp, req)

        result, err := ioutil.ReadAll(resp.Body)
        if err != nil {
          t.Errorf("handlers() err: %v", err)
        }

        got := string(result)

        if string(got) != tt.want {
          t.Errorf("handlers() = %v, want %v", got, tt.want)
        }
      })
    }
}

Let us split this up:

Now for each test case we run, we create a new request which we use to call on our handlers, here we pass the method and query arguments as parameters.

We do the requst to our handler with the handler.ServeHTTP function, which takes our resp and req as parameters. We get the result from the request by ioutil.ReadAll with the resp.Body as a paramter.

All we have to do now is to convert the result we got into a string, and compare what we got with what we want. As you can see (hopefully), the test passes. If you go back to main.go and change “Hello world!” to something else, and rerun the test it will fail.

Thank you for reading.