Create an HTTP server using Gin is quite easy. While developing an application using Gin, I’m stumbled on how to test the JSON response using Gin.

As always, Google is your friend. After search for some hours, I actually pulled off how to write test using Gin. Let’s create a simple application with a single endpoint and it response with JSON {"message": "Welcome!"}.

main.go
  • go
1
2
3
4
5
6
7
8
9
10
11
package main

import (
    "router/router"
)

func main() {
    r := router.SetupRouter("Welcome")

    r.Run()
}

Now let’s create a router file

router.go
  • go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package router

import (
   "github.com/gin-gonic/gin"
)

// For example purpose, let's inject response message here
func SetupRouter(message string) *gin.Engine {
    r := gin.Default()

    r.GET("/", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": message,
		})
	})

    return r
}

After that, let’s create a test file to test our router

router_test.go
  • go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package router

import (
   "encoding/json"
   "net/http"
   "net/http/httptest"
   "testing"

   "github.com/gin-gonic/gin"
   "github.com/stretchr/testify/assert"
)

var tests = []struct {
    message   string
    expectedMessage string
}{
    {"Welcome!", "Welcome!"},
    {"Hello", "Hello"},
}

func doRequest(r http.Handler, method, path string) *httptest.ResponseRecorder {
    req, _ := http.NewRequest(method, path, nil)
    w := httptest.NewRecorder()
    r.ServeHTTP(w, req)

    return w
}

func TestWelcome(t *testing.T) {
    gin.SetMode(gin.TestMode)

    for _, e := range tests {
        // setup router
        router := SetupRouter(e.message)

        // do a GET request to our router
        w := doRequest(router, "GET", "/")

        // assert if we got 200 on every request
        assert.Equal(t, http.StatusOK, w.Code)

        // for simplicity, let's unmarshal the body response to a map of string
        // you should use struct for a real application tho
        var response map[string]string
        err := json.Unmarshal([]byte(w.Body.String()), &response)

        // get the value
        res, exists := response["message"]

        // assert if the response are correct
        assert.Nil(t, err)
        assert.True(t, exists)
        assert.Equal(t, e.message, res)
    }
}

Run the tests with go test inside folder or you can run test recursively using go test ./.... It will show

$ go test .
ok      router/router   0.009s

References