A handler test example

A handler test example

Posted

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:

  • args is the parameters we want to pass into each test function. In this case the method will be GET and query equal to /hello.
  • tests is all test cases that we would like to run.
    • name is the name of our test case (optional).
    • want is simply what we expect when we run the test.
  • handler is the simple mux router we wrote our main.go file.
  • resp is used to record whatever we get as a response to the different test cases that we run.

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.