-
Hello everyone, I am learning go and I have picked up echo to learn web develop with it, so please be patient with me. I have two questions I will separate them to make things easier
So let me illustrate the scenario, I have a endpoint that store messages in the database and associate it to a user, when there is no user it returns to me: echo.NewHTTPError(http.StatusBadRequest, "Database Error") I am trying to write a test for this behavior, I tried following the documentation, but could not find a way to test it. I will paste my test here:
The test pass on the first two iterations which is configured to return this on the code:
I am pretty sure I am handing it the wrong way, since one is c.String and the other is echo.NewHTTPError. But I am not sure how to handle it.
This is another thing I am struggling, I wrote a validator per as documentation: https://echo.labstack.com/guide/request/#validate-data However, I would like to give an error with the key value is incorrect in a POST request, for example:
This kind of request validate can not validate, since it binds the correct values to the struct. To be honest, I am not sure while building an API I should give Bad Requests to this kind of extra information or just accept it. These are my questions, |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
If you are testing handlers directly ala type CustomValidator struct {
validator *validator.Validate
}
func (cv *CustomValidator) Validate(i interface{}) error {
if err := cv.validator.Struct(i); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
}
return nil
}
type User struct {
Name string `json:"name" validate:"required"`
Email string `json:"email" validate:"required,email"`
}
type handler struct {
}
func (h *handler) create(c echo.Context) error {
u := new(User)
if err := c.Bind(u); err != nil {
return err
}
if err := c.Validate(u); err != nil {
return err
}
return c.JSON(http.StatusOK, u)
} func TestHandler_create1(t *testing.T) {
var testCases = []struct {
name string
whenURL string
whenBody string
expectBody string
expectStatus int
}{
{
name: "ok",
whenURL: "/123",
whenBody: `{"name":"John Doe","email":"[email protected]"}`,
expectStatus: http.StatusOK,
expectBody: "{\"name\":\"John Doe\",\"email\":\"[email protected]\"}\n",
},
{
name: "nok",
whenURL: "/123",
whenBody: `{"name":"John Doe","email":"x"}`,
expectStatus: http.StatusBadRequest,
expectBody: "{\"message\":\"Key: 'User.Email' Error:Field validation for 'Email' failed on the 'email' tag\"}\n",
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
e := echo.New()
e.Validator = &CustomValidator{validator: validator.New()}
h := handler{}
e.POST("/:uid", h.create)
req := httptest.NewRequest(http.MethodPost, tc.whenURL, strings.NewReader(tc.whenBody))
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
rec := httptest.NewRecorder()
e.ServeHTTP(rec, req)
assert.Equal(t, tc.expectStatus, rec.Code)
assert.Equal(t, tc.expectBody, rec.Body.String())
})
}
} func TestHandler_create2(t *testing.T) {
var testCases = []struct {
name string
whenURL string
whenBody string
expectBody string
expectStatus int
expectError error
}{
{
name: "ok",
whenURL: "/123",
whenBody: `{"name":"John Doe","email":"[email protected]"}`,
expectError: nil,
expectStatus: http.StatusOK,
expectBody: "{\"name\":\"John Doe\",\"email\":\"[email protected]\"}\n",
},
{
name: "nok",
whenURL: "/123",
whenBody: `{"name":"John Doe","email":"x"}`,
expectError: echo.NewHTTPError(http.StatusBadRequest, "Key: 'User.Email' Error:Field validation for 'Email' failed on the 'email' tag"),
expectStatus: http.StatusOK, // is also 200 because this is default code
expectBody: ``,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
e := echo.New()
e.Validator = &CustomValidator{validator: validator.New()}
req := httptest.NewRequest(http.MethodPost, tc.whenURL, strings.NewReader(tc.whenBody))
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
h := handler{}
err := h.create(c)
if tc.expectError != nil {
assert.EqualError(t, err, tc.expectError.Error())
} else {
assert.NoError(t, err)
}
assert.Equal(t, tc.expectBody, rec.Body.String())
assert.Equal(t, tc.expectStatus, rec.Code)
})
}
} |
Beta Was this translation helpful? Give feedback.
-
Thank you for your answers, it worked. What I do not understand is why in the second test case you showed me, the status code is 200 and the expected body is empty. |
Beta Was this translation helpful? Give feedback.
If you are testing handlers directly ala
handler.PostUser(c)
then you need to have IF block to check if result was an error and if it is - check it against expected error. You could usee.ServeHTTP(rec, req)
to test whole flow including middlewares (if they are set)