Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test http request handlers

Tags:

http

testing

go

I have a set of requests handlers like the one below:

func GetProductsHandler(w http.ResponseWriter, req *http.Request) {
    defer req.Body.Close()
    products := db.GetProducts()

    //    ...
    // return products as JSON array
}

How do I test them the right way? Should I send mock ResponseWriter and Request objects to the function and see the results?

Are there tools to mock request and response objects in Go to simplify the process without having to start server before testing?

like image 992
Sergei Basharov Avatar asked Nov 18 '16 15:11

Sergei Basharov


1 Answers

Go provides a mock writer for use in testing handlers. The standard library documentation provides an example:

package main

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

func main() {
    handler := func(w http.ResponseWriter, r *http.Request) {
        http.Error(w, "something failed", http.StatusInternalServerError)
    }

    req := httptest.NewRequest("GET", "http://example.com/foo", nil)
    w := httptest.NewRecorder()
    handler(w, req)

    fmt.Printf("%d - %s", w.Code, w.Body.String())
}

I think having a global dependency (db) throws a wrench into clean unit testing. Using go your test could reassign a value, masking, the global value of db.

Another strategy (my preferred) is to package your handler in a struct, which has a db attribute..

type Handlers struct {
  db DB_INTERFACE
}

func (hs *Handlers) GetProductsHandler(w http.ResponseWriter, req *http.Request) {...}

This way your test can instantiate a Handlers with a stub db object which will allow you to create IO free unit tests.

like image 142
dm03514 Avatar answered Sep 20 '22 00:09

dm03514