Skip to main content

Testing

Testing Handler

GET /users/:id

Handler below retrieves user by id from the database. If user is not found it returns 404 error with a message.

CreateUser

POST /users

  • Accepts JSON payload
  • On success 201 - Created
  • On error 500 - Internal Server Error

GetUser

GET /users/:email

  • On success 200 - OK
  • On error 404 - Not Found if user is not found otherwise 500 - Internal Server Error

handler.go

package handler

import(
"net/http"

"github.com/labstack/echo/v5"
)

type(
User struct{
Name string`json:"name" form:"name"`
Email string`json:"email" form:"email"`
}
handler struct{
db map[string]*User
}
)

func(h *handler)createUser(c *echo.Context)error{
u :=new(User)
if err := c.Bind(u); err !=nil{
return err
}
return c.JSON(http.StatusCreated, u)
}

func(h *handler)getUser(c *echo.Context)error{
email := c.Param("email")
user := h.db[email]
if user ==nil{
return echo.NewHTTPError(http.StatusNotFound,"user not found")
}
return c.JSON(http.StatusOK, user)
}

handler_test.go

package handler

import(
"net/http"
"net/http/httptest"
"strings"
"testing"

"github.com/labstack/echo/v5"
"github.com/labstack/echo/v5/echotest"
"github.com/stretchr/testify/assert"
)

var(
mockDB =map[string]*User{
"[email protected]":&User{"Jon Snow","[email protected]"},
}
userJSON =`{"name":"Jon Snow","email":"[email protected]"}`
)

funcTestCreateUser(t *testing.T){
// Setup
e := echo.New()
req := httptest.NewRequest(http.MethodPost,"/", strings.NewReader(userJSON))
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)

rec := httptest.NewRecorder()
c := e.NewContext(req, rec)

h :=&controller{mockDB}

// Assertions
if assert.NoError(t, h.createUser(c)){
assert.Equal(t, http.StatusCreated, rec.Code)
assert.Equal(t, userJSON, rec.Body.String())
}
}

// Same test as above but using `echotest` package helpers
funcTestCreateUserWithEchoTest(t *testing.T){
c, rec := echotest.ContextConfig{
Headers:map[string][]string{
echo.HeaderContentType:{echo.MIMEApplicationJSON},
},
JSONBody:[]byte(`{"name":"Jon Snow","email":"[email protected]"}`),
}.ToContextRecorder(t)

h :=&controller{mockDB}

// Assertions
if assert.NoError(t, h.createUser(c)){
assert.Equal(t, http.StatusCreated, rec.Code)
assert.Equal(t, userJSON+"\n", rec.Body.String())
}
}

// Same test as above but even shorter
funcTestCreateUserWithEchoTest2(t *testing.T){
h :=&controller{mockDB}

rec := echotest.ContextConfig{
Headers:map[string][]string{
echo.HeaderContentType:{echo.MIMEApplicationJSON},
},
JSONBody:[]byte(`{"name":"Jon Snow","email":"[email protected]"}`),
}.ServeWithHandler(t, h.createUser)

assert.Equal(t, http.StatusCreated, rec.Code)
assert.Equal(t, userJSON+"\n", rec.Body.String())
}

funcTestGetUser(t *testing.T){
// Setup
e := echo.New()
req := httptest.NewRequest(http.MethodGet,"/",nil)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)

c.SetPath("/users/:email")
c.SetPathValues(echo.PathValues{
{Name:"email", Value:"[email protected]"},
})
h :=&controller{mockDB}

// Assertions
if assert.NoError(t, h.getUser(c)){
assert.Equal(t, http.StatusOK, rec.Code)
assert.Equal(t, userJSON, rec.Body.String())
}
}

funcTestGetUserWithEchoTest(t *testing.T){
c, rec := echotest.ContextConfig{
PathValues: echo.PathValues{
{Name:"email", Value:"[email protected]"},
},
Headers:map[string][]string{
echo.HeaderContentType:{echo.MIMEApplicationJSON},
},
JSONBody:[]byte(userJSON),
}.ToContextRecorder(t)

h :=&controller{mockDB}

// Assertions
if assert.NoError(t, h.getUser(c)){
assert.Equal(t, http.StatusOK, rec.Code)
assert.Equal(t, userJSON+"\n", rec.Body.String())
}
}

Using Form Payload

// import "net/url"
f :=make(url.Values)
f.Set("name","Jon Snow")
f.Set("email","[email protected]")
req := httptest.NewRequest(http.MethodPost,"/", strings.NewReader(f.Encode()))
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationForm)

Multipart form payload:

funcTestContext_MultipartForm(t *testing.T){
testConf := echotest.ContextConfig{
MultipartForm:&echotest.MultipartForm{
Fields:map[string]string{
"key":"value",
},
Files:[]echotest.MultipartFormFile{
{
Fieldname:"file",
Filename:"test.json",
Content: echotest.LoadBytes(t,"testdata/test.json"),
},
},
},
}
c := testConf.ToContext(t)

assert.Equal(t,"value", c.FormValue("key"))
assert.Equal(t, http.MethodPost, c.Request().Method)
assert.Equal(t,true, strings.HasPrefix(c.Request().Header.Get(echo.HeaderContentType),"multipart/form-data; boundary="))

fv, err := c.FormFile("file")
if err !=nil{
t.Fatal(err)
}
assert.Equal(t,"test.json", fv.Filename)
}

Setting Path Params

c.SetPathValues(echo.PathValues{
{Name:"id", Value:"1"},
{Name:"email", Value:"[email protected]"},
})

Setting Query Params

// import "net/url"
q :=make(url.Values)
q.Set("email","[email protected]")
req := httptest.NewRequest(http.MethodGet,"/?"+q.Encode(),nil)

Testing Middleware

funcTestCreateUserWithEchoTest2(t *testing.T){
handler :=func(c *echo.Context)error{
return c.JSON(http.StatusTeapot, fmt.Sprintf("email: %s", c.Param("email")))
}
middleware :=func(next echo.HandlerFunc) echo.HandlerFunc {
returnfunc(c *echo.Context)error{
c.Set("user_id",int64(1234))
returnnext(c)
}
}

c, rec := echotest.ContextConfig{
PathValues: echo.PathValues{{Name:"email", Value:"[email protected]"}},
}.ToContextRecorder(t)

err :=middleware(handler)(c)
if err !=nil{
t.Fatal(err)
}
// check that middleware set the value
userID, err := echo.ContextGet[int64](c,"user_id")
assert.NoError(t, err)
assert.Equal(t,int64(1234), userID)

// check that handler returned the correct response
assert.Equal(t, http.StatusTeapot, rec.Code)
}

For now you can look into built-in middleware test cases.

AltStyle によって変換されたページ (->オリジナル) /