0

I have a function to create user which is working properly. Now I have to mock Prepare and SaveUser function inside CreateUser. But that CreateUser require json data as request parameter. Below is my CreateUser function.

func (server *Server) CreateUser(c *gin.Context) {
    errList = map[string]string{}
    user := models.User{}
    if err := c.ShouldBindJSON(&user); err != nil {
        log.Println(err)
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})  **//every time return from here with error -> invalid request**
        return
    }
    user.Prepare()

    userCreated, err := sqlstore.SaveUser(&user)
    if err != nil {
        formattedError := formaterror.FormatError(err.Error())
        errList = formattedError
        c.JSON(http.StatusInternalServerError, gin.H{
            "status": http.StatusInternalServerError,
            "error":  errList,
        })
        return
    }

    c.JSON(http.StatusCreated, gin.H{
        "status":   http.StatusCreated,
        "response": userCreated,
    })
}

This is required json data as request parameter for above create user. I want to pass below data while mocking.

{"firstname":"test","email":"test@test.com"}

Below is test case to mock above create user function.

type UserMock struct {
    mock.Mock
}
func (u *UserMock) Prepare() (string, error) {
    args := u.Called()
    return args.String(0), args.Error(1)
}
func (u *UserMock) SaveUser() (string, error) {
    args := u.Called()
    return args.String(0), args.Error(1)
}
func TestCreateUser(t *testing.T) {
    gin.SetMode(gin.TestMode)
    w := httptest.NewRecorder()
    c, _ := gin.CreateTestContext(w)
    **//how to json data as request parameter**
    uMock := UserMock{}
    uMock.On("Prepare").Return("mocktest", nil)
    server := Server{}
    server.CreateUser(c)
    if w.Code != 201 {
        t.Error("Unexpected status code found : ",w.Code)
    }
}

Thanks in advance.

Amit Upa
  • 307
  • 1
  • 2
  • 13
  • 1
    What is your question? – Adrian Mar 26 '20 at 19:52
  • @Adrian how do i pass json data as a request parameter. Like I want to set ```{"firstname":"test","email":"test@test.com"}``` gin context (c) so that when i run test case ```c.ShouldBindJSON()``` this should not give me an error – Amit Upa Mar 26 '20 at 19:59

1 Answers1

1

You need to add a strings.NewReader(string(myjson)) on a new request. Please check this and take it as a template on your current GIN Code.

// TestCreateUser new test
func TestCreateUser(t *testing.T) {

    // Setup Recorder, TestContext, Router
    router := getRouter(true)
    w := httptest.NewRecorder()
    c, _ := gin.CreateTestContext(w)

    // set JSON body
    jsonParam := `{"firstname":"test","email":"test@test.com"}`

    // Mock HTTP Request and it's return
    req, err := http.NewRequest("POST", "/user", strings.NewReader(string(jsonParam)))

    // make sure request was executed
    assert.NoError(t, err)

    // Serve Request and recorded data
    router.ServeHTTP(w, req)

    // Test results
    assert.Equal(t, 200, w.Code)
    assert.Equal(t, nil, w.Body.String()) 
    // check your response since nil isn't valid return

}
Eddwin Paz
  • 2,842
  • 4
  • 28
  • 48
  • This is done using mux router. Can we use gin router instead. – Amit Upa Mar 26 '20 at 21:15
  • @AmitUpa as I mention is a template, please check the http.NewRequest() in order to mock the request. and pass your JSON along the data. I'll try to do it for Gin. later today. Tought you would understand the idea... :) no worry. – Eddwin Paz Mar 26 '20 at 21:26
  • @AmitUpa can you please check again the answer, it's updated. – Eddwin Paz Mar 26 '20 at 22:01
  • Hey @Eddwin, Thanks for your answer, I check your answer it is working but i can not mock ```Prepare() and SaveUser()``` – Amit Upa Mar 26 '20 at 23:03
  • @AmitUpa since you are doing a end-to-end testing. you need to mock your user entity and pass it along the request with the router handler; that means having to pass the http method, parameters, and the expected return. what coding pattern are you using here? because I see some gaps on the structs that you are presenting like server{} struct and userMock does not contain anything. – Eddwin Paz Mar 26 '20 at 23:54
  • now that you have the request mock you need to use your router and use the CreateUser function. and pass the userMock which will be the data that your function will be returning. I will add more code to show you.. – Eddwin Paz Mar 26 '20 at 23:58