|
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, |
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":"jd@test.com"}`,
expectStatus: http.StatusOK,
expectBody: "{\"name\":\"John Doe\",\"email\":\"jd@test.com\"}\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":"jd@test.com"}`,
expectError: nil,
expectStatus: http.StatusOK,
expectBody: "{\"name\":\"John Doe\",\"email\":\"jd@test.com\"}\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)
})
}
} |
|
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. |
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)