package api import ( "bytes" "encoding/json" "io" "net/http" "net/http/httptest" "testing" "github.com/gin-gonic/gin" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" db "github.com/FernandoJVideira/simple_bank/internal/db/sqlc" "github.com/FernandoJVideira/simple_bank/internal/domain/role" "github.com/FernandoJVideira/simple_bank/internal/handlers/http/response" "github.com/FernandoJVideira/simple_bank/internal/security" "github.com/FernandoJVideira/simple_bank/internal/service" mocksvc "github.com/FernandoJVideira/simple_bank/internal/service/mock" "github.com/FernandoJVideira/simple_bank/pkg/testutil" ) func randomUser(t *testing.T) (user db.User, password string) { password = testutil.RandomString(6) hashedPassword, err := security.HashPassword(password) if err != nil { t.Fatal(err) } user = db.User{ Username: testutil.RandomOwner(), HashedPassword: hashedPassword, Role: role.MemberRole, FullName: testutil.RandomOwner(), Email: testutil.RandomEmail(), } return } func TestCreateUserAPI(t *testing.T) { user, password := randomUser(t) testCases := []struct { name string body gin.H buildStubs func(userService *mocksvc.MockUserService) checkResponse func(t *testing.T, recorder *httptest.ResponseRecorder) }{ { name: "OK", body: gin.H{ "username": user.Username, "password": password, "full_name": user.FullName, "email": user.Email, }, buildStubs: func(userService *mocksvc.MockUserService) { servcArg := service.RegisterUserRequest{ Username: user.Username, Password: password, FullName: user.FullName, Email: user.Email, } userService.EXPECT(). CreateUser(gomock.Any(), servcArg). Times(1). Return(&service.RegisterUserResponse{ User: user, }, nil) }, checkResponse: func(t *testing.T, recorder *httptest.ResponseRecorder) { require.Equal(t, http.StatusCreated, recorder.Code) requireBodyMatchUser(t, recorder.Body, user) }, }, } for i := range testCases { tc := testCases[i] t.Run(tc.name, func(t *testing.T) { storeCtrl := gomock.NewController(t) defer storeCtrl.Finish() userCtrl := gomock.NewController(t) defer userCtrl.Finish() userService := mocksvc.NewMockUserService(userCtrl) tc.buildStubs(userService) // Start test server and send request s := newTestServer(t, nil, nil, userService, nil) recorder := httptest.NewRecorder() data, err := json.Marshal(tc.body) require.NoError(t, err) url := "/api/v1/auth/register" req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(data)) require.NoError(t, err) s.router.ServeHTTP(recorder, req) tc.checkResponse(t, recorder) }) } } func requireBodyMatchUser(t *testing.T, body *bytes.Buffer, user db.User) { data, err := io.ReadAll(body) require.NoError(t, err) var gotUser db.User var resp response.JSONResponse err = json.Unmarshal(data, &resp) require.NoError(t, err) data, err = json.Marshal(resp.Data) require.NoError(t, err) err = json.Unmarshal(data, &gotUser) require.NoError(t, err) require.Equal(t, user.Username, gotUser.Username) require.Equal(t, user.FullName, gotUser.FullName) require.Equal(t, user.Email, gotUser.Email) }