From d38c3cb6618d64ea0470f5b0623608d3c9349050 Mon Sep 17 00:00:00 2001 From: Dieg0Code Date: Sat, 17 Aug 2024 23:15:15 -0400 Subject: [PATCH] add tests for api-users --- .../controllers/user_controller_impl_test.go | 264 ++++++++++ .../repository/user_repository_impl_test.go | 231 +++++++++ api-users/services/user_service_impl_test.go | 472 ++++++++++++++++++ 3 files changed, 967 insertions(+) create mode 100644 api-users/controllers/user_controller_impl_test.go create mode 100644 api-users/repository/user_repository_impl_test.go create mode 100644 api-users/services/user_service_impl_test.go diff --git a/api-users/controllers/user_controller_impl_test.go b/api-users/controllers/user_controller_impl_test.go new file mode 100644 index 0000000..924ad8e --- /dev/null +++ b/api-users/controllers/user_controller_impl_test.go @@ -0,0 +1,264 @@ +package controllers + +import ( + "bytes" + "encoding/json" + "errors" + "net/http" + "net/http/httptest" + "testing" + + "github.com/dieg0code/shared/json/request" + "github.com/dieg0code/shared/json/response" + "github.com/dieg0code/shared/mocks" + "github.com/gin-gonic/gin" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" +) + +func TestLogInUser(t *testing.T) { + t.Run("LogInUser_Success", func(t *testing.T) { + userService := new(mocks.MockUserService) + userController := NewUserControllerImpl(userService) + + gin.SetMode(gin.TestMode) + + router := gin.Default() + + router.POST("/login", userController.LogInUser) + + userService.On("LogInUser", mock.Anything).Return(response.LogInUserResponse{ + Token: "token", + }, nil) + + loginRequest := request.LogInUserRequest{ + Email: "test@test.com", + Password: "password", + } + + reqBody, err := json.Marshal(loginRequest) + assert.NoError(t, err, "Expected no error marshalling request body") + + req, err := http.NewRequest(http.MethodPost, "/login", bytes.NewBuffer(reqBody)) + assert.NoError(t, err, "Expected no error creating request") + + rec := httptest.NewRecorder() + router.ServeHTTP(rec, req) + + assert.Equal(t, http.StatusOK, rec.Code, "Expected status code 200") + + var response response.BaseResponse + err = json.Unmarshal(rec.Body.Bytes(), &response) + assert.NoError(t, err, "Expected no error unmarshalling response body") + assert.Equal(t, "success", response.Status, "Expected response status to be success") + assert.Equal(t, "User logged in successfully", response.Message, "Expected response message to be 'User logged in successfully'") + assert.Equal(t, "Bearer token", rec.Header().Get("Authorization"), "Expected Authorization header to be 'Bearer token'") + assert.Equal(t, "token", response.Data.(map[string]interface{})["token"], "Expected response data token to be 'token'") + userService.AssertExpectations(t) + }) + + t.Run("LogInUser_ErrorBindingJSON", func(t *testing.T) { + userService := new(mocks.MockUserService) + userController := NewUserControllerImpl(userService) + + gin.SetMode(gin.TestMode) + + router := gin.Default() + + router.POST("/login", userController.LogInUser) + + req, err := http.NewRequest(http.MethodPost, "/login", bytes.NewBuffer([]byte(""))) + assert.NoError(t, err, "Expected no error creating request") + + rec := httptest.NewRecorder() + router.ServeHTTP(rec, req) + + assert.Equal(t, http.StatusBadRequest, rec.Code, "Expected status code 400") + + var response response.BaseResponse + err = json.Unmarshal(rec.Body.Bytes(), &response) + assert.NoError(t, err, "Expected no error unmarshalling response body") + assert.Equal(t, "error", response.Status, "Expected response status to be error") + assert.Equal(t, "Invalid request body", response.Message, "Expected response message to be 'Invalid request body'") + + userService.AssertExpectations(t) + }) + + t.Run("LogInUser_ErrorLoggingInUser", func(t *testing.T) { + userService := new(mocks.MockUserService) + userController := NewUserControllerImpl(userService) + + gin.SetMode(gin.TestMode) + + router := gin.Default() + + router.POST("/login", userController.LogInUser) + + userService.On("LogInUser", mock.Anything).Return(response.LogInUserResponse{}, assert.AnError) + + loginRequest := request.LogInUserRequest{ + Email: "test@test.com", + Password: "password", + } + + reqBody, err := json.Marshal(loginRequest) + assert.NoError(t, err, "Expected no error marshalling request body") + + req, err := http.NewRequest(http.MethodPost, "/login", bytes.NewBuffer(reqBody)) + assert.NoError(t, err, "Expected no error creating request") + + rec := httptest.NewRecorder() + router.ServeHTTP(rec, req) + + assert.Equal(t, http.StatusInternalServerError, rec.Code, "Expected status code 500") + + var response response.BaseResponse + err = json.Unmarshal(rec.Body.Bytes(), &response) + assert.NoError(t, err, "Expected no error unmarshalling response body") + assert.Equal(t, "error", response.Status, "Expected response status to be error") + assert.Equal(t, "Error logging in user", response.Message, "Expected response message to be 'Error logging in user'") + + userService.AssertExpectations(t) + }) +} + +func TestGetAllUsers(t *testing.T) { + t.Run("GetAllUsers_Success", func(t *testing.T) { + userService := new(mocks.MockUserService) + userController := NewUserControllerImpl(userService) + + gin.SetMode(gin.TestMode) + + router := gin.Default() + + router.GET("/users", userController.GetAllUsers) + + userService.On("GetAllUsers").Return([]response.UserResponse{ + { + UserID: "uuid", + Email: "test@test.com", + Username: "test", + }, + { + UserID: "uuid2", + Email: "test2@test.com", + Username: "test2", + }, + }, nil) + + req, err := http.NewRequest(http.MethodGet, "/users", nil) + assert.NoError(t, err, "Expected no error creating request") + + rec := httptest.NewRecorder() + router.ServeHTTP(rec, req) + + assert.Equal(t, http.StatusOK, rec.Code, "Expected status code 200") + + var response response.BaseResponse + err = json.Unmarshal(rec.Body.Bytes(), &response) + assert.NoError(t, err, "Expected no error unmarshalling response body") + assert.Equal(t, "success", response.Status, "Expected response status to be success") + assert.Equal(t, "Success getting all users", response.Message, "Expected response message to be 'Success getting all users'") + assert.Equal(t, 2, len(response.Data.([]interface{})), "Expected response data to have 2 users") + + userService.AssertExpectations(t) + + }) + + t.Run("GetAllUsers_ErrorGettingAllUsers", func(t *testing.T) { + userService := new(mocks.MockUserService) + userController := NewUserControllerImpl(userService) + + gin.SetMode(gin.TestMode) + + router := gin.Default() + + router.GET("/users", userController.GetAllUsers) + + userService.On("GetAllUsers").Return([]response.UserResponse{}, assert.AnError) + + req, err := http.NewRequest(http.MethodGet, "/users", nil) + assert.NoError(t, err, "Expected no error creating request") + + rec := httptest.NewRecorder() + router.ServeHTTP(rec, req) + + assert.Equal(t, http.StatusInternalServerError, rec.Code, "Expected status code 500") + + var response response.BaseResponse + err = json.Unmarshal(rec.Body.Bytes(), &response) + assert.NoError(t, err, "Expected no error unmarshalling response body") + assert.Equal(t, "error", response.Status, "Expected response status to be error") + assert.Equal(t, "Error getting all users", response.Message, "Expected response message to be 'Error getting all users'") + + userService.AssertExpectations(t) + }) + +} + +func TestGetUserByID(t *testing.T) { + t.Run("GetUserByID_Success", func(t *testing.T) { + userService := new(mocks.MockUserService) + userController := NewUserControllerImpl(userService) + + gin.SetMode(gin.TestMode) + + router := gin.Default() + + router.GET("/users/:userID", userController.GetUserByID) + + userID := "uuid" + + userService.On("GetUserByID", userID).Return(response.UserResponse{ + UserID: "uuid", + Username: "test", + Email: "test@test.com", + }, nil) + + req, err := http.NewRequest(http.MethodGet, "/users/uuid", nil) + assert.NoError(t, err, "Expected no error creating request") + + rec := httptest.NewRecorder() + router.ServeHTTP(rec, req) + + assert.Equal(t, http.StatusOK, rec.Code, "Status code shoud be 200") + + var response response.BaseResponse + err = json.Unmarshal(rec.Body.Bytes(), &response) + assert.NoError(t, err, "Expected no error unmarshalling response body") + assert.Equal(t, "success", response.Status, "Expected response status to be 'success'") + + userService.AssertExpectations(t) + + }) + + t.Run("GetUserByID_Error", func(t *testing.T) { + userService := new(mocks.MockUserService) + userController := NewUserControllerImpl(userService) + + gin.SetMode(gin.TestMode) + + router := gin.Default() + + router.GET("/users/:userID", userController.GetUserByID) + + userID := "invalid-id" + + userService.On("GetUserByID", userID).Return(response.UserResponse{}, errors.New("error getting user")) + + req, err := http.NewRequest(http.MethodGet, "/users/invalid-id", nil) + assert.NoError(t, err, "Expected no error creating request") + + rec := httptest.NewRecorder() + router.ServeHTTP(rec, req) + + assert.Equal(t, http.StatusInternalServerError, rec.Code, "Status code shoud be 500") + + var response response.BaseResponse + err = json.Unmarshal(rec.Body.Bytes(), &response) + assert.NoError(t, err, "Expected no error unmarshalling response body") + assert.Equal(t, "error", response.Status, "Expected response status to be 'error'") + + userService.AssertExpectations(t) + }) +} diff --git a/api-users/repository/user_repository_impl_test.go b/api-users/repository/user_repository_impl_test.go new file mode 100644 index 0000000..780f3f8 --- /dev/null +++ b/api-users/repository/user_repository_impl_test.go @@ -0,0 +1,231 @@ +package repository + +import ( + "errors" + "testing" + + "github.com/aws/aws-sdk-go/service/dynamodb" + "github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute" + "github.com/dieg0code/shared/mocks" + "github.com/dieg0code/shared/models" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" +) + +func TestUserRepositoryImpl_GetByEmail(t *testing.T) { + t.Run("GetByEmail_Success", func(t *testing.T) { + mockDB := new(mocks.MockDynamoDB) + repo := NewUserRepositoryImpl(mockDB, "test-table") + + expectedResult := models.User{ + UserID: "test-id", + Email: "testing@test.com", + Username: "test", + Password: "test", + Role: "user", + } + + item, err := dynamodbattribute.MarshalMap(expectedResult) + assert.NoError(t, err, "Expected no error marshalling map") + + mockDB.On("Query", mock.Anything).Return(&dynamodb.QueryOutput{ + Items: []map[string]*dynamodb.AttributeValue{item}, + }, nil) + + result, err := repo.GetByEmail("testing@test.com") + assert.NoError(t, err, "Expected no error getting user") + assert.Equal(t, expectedResult, result, "Expected user to be equal") + + mockDB.AssertExpectations(t) + }) + + t.Run("GetByEmail_UserNotFound", func(t *testing.T) { + mockDB := new(mocks.MockDynamoDB) + repo := NewUserRepositoryImpl(mockDB, "test-table") + + mockDB.On("Query", mock.Anything).Return(&dynamodb.QueryOutput{ + Items: []map[string]*dynamodb.AttributeValue{}, + }, nil) + + _, err := repo.GetByEmail("nonexistent@test.com") + + assert.Error(t, err, "Expected error getting user") + assert.Equal(t, "user not found", err.Error(), "Expected error message to be 'user not found'") + + mockDB.AssertExpectations(t) + }) + + t.Run("GetByEmail_QueryError", func(t *testing.T) { + mockDB := new(mocks.MockDynamoDB) + repo := NewUserRepositoryImpl(mockDB, "test-table") + + mockDB.On("Query", mock.Anything).Return(&dynamodb.QueryOutput{}, errors.New("error getting user")) + + _, err := repo.GetByEmail("testing@test.com") + + assert.Error(t, err, "Expected error getting user") + assert.Equal(t, "error getting user", err.Error(), "Expected error message to be 'error getting user'") + + mockDB.AssertExpectations(t) + }) +} + +func TestUserRepositoryImpl_Create(t *testing.T) { + t.Run("Create_Success", func(t *testing.T) { + mockDB := new(mocks.MockDynamoDB) + repo := NewUserRepositoryImpl(mockDB, "test-table") + + user := models.User{ + UserID: "test-id", + Username: "test", + Email: "testing@email.com", + Password: "test", + Role: "user", + } + + mockDB.On("PutItem", mock.Anything).Return(&dynamodb.PutItemOutput{}, nil) + + result, err := repo.Create(user) + assert.NoError(t, err, "Expected no error creating user") + + assert.Equal(t, user, result, "Expected user to be equal") + + mockDB.AssertExpectations(t) + }) + + t.Run("Create_Error", func(t *testing.T) { + mockDB := new(mocks.MockDynamoDB) + repo := NewUserRepositoryImpl(mockDB, "test-table") + + user := models.User{ + UserID: "test-id", + Username: "test", + Email: "testing@test.com", + Password: "test", + Role: "user", + } + + mockDB.On("PutItem", mock.Anything).Return(&dynamodb.PutItemOutput{}, errors.New("error creating user")) + + _, err := repo.Create(user) + assert.Error(t, err, "Expected error creating user") + + assert.Equal(t, "error creating user", err.Error(), "Expected error message to be 'error creating user'") + + mockDB.AssertExpectations(t) + }) +} + +func TestUserRepositoryImpl_GetAll(t *testing.T) { + t.Run("GetAll_Success", func(t *testing.T) { + mockDB := new(mocks.MockDynamoDB) + repo := NewUserRepositoryImpl(mockDB, "test-table") + + expectedResult := []models.User{ + { + UserID: "test-id", + Email: "testing@test.com", + Username: "test", + Password: "test", + Role: "user", + }, + { + UserID: "test-id-2", + Email: "test2@test.com", + Username: "test2", + Password: "test2", + Role: "user", + }, + } + + item1, err := dynamodbattribute.MarshalMap(expectedResult[0]) + assert.NoError(t, err, "Expected no error marshalling map") + + item2, err := dynamodbattribute.MarshalMap(expectedResult[1]) + assert.NoError(t, err, "Expected no error marshalling map") + + mockDB.On("Scan", mock.Anything).Return(&dynamodb.ScanOutput{ + Items: []map[string]*dynamodb.AttributeValue{item1, item2}, + }, nil).Once() + + result, err := repo.GetAll() + assert.NoError(t, err, "Expected no error getting users") + + assert.Equal(t, expectedResult, result, "Expected users to be equal") + + mockDB.AssertExpectations(t) + }) + + t.Run("GetAll_Error", func(t *testing.T) { + mockDB := new(mocks.MockDynamoDB) + repo := NewUserRepositoryImpl(mockDB, "test-table") + + mockDB.On("Scan", mock.Anything).Return(&dynamodb.ScanOutput{}, errors.New("error getting users")) + + _, err := repo.GetAll() + assert.Error(t, err, "Expected error getting users") + + assert.Equal(t, "error getting users", err.Error(), "Expected error message to be 'error getting users'") + + mockDB.AssertExpectations(t) + }) +} + +func TestUserRepositoryImpl_GetByID(t *testing.T) { + t.Run("GetByID_Success", func(t *testing.T) { + mockDB := new(mocks.MockDynamoDB) + repo := NewUserRepositoryImpl(mockDB, "test-table") + + expectedResult := models.User{ + UserID: "test-id", + Email: "test@test.com", + Username: "test", + Password: "test", + Role: "user", + } + + item, err := dynamodbattribute.MarshalMap(expectedResult) + assert.NoError(t, err, "Expected no error marshalling map") + + mockDB.On("GetItem", mock.Anything).Return(&dynamodb.GetItemOutput{ + Item: item, + }, nil).Once() + + result, err := repo.GetByID("test-id") + assert.NoError(t, err, "Expected no error getting user") + + assert.Equal(t, expectedResult, result, "Expected user to be equal") + + mockDB.AssertExpectations(t) + + }) + + t.Run("GetByID_UserNotFound", func(t *testing.T) { + mockDB := new(mocks.MockDynamoDB) + repo := NewUserRepositoryImpl(mockDB, "test-table") + + mockDB.On("GetItem", mock.Anything).Return(&dynamodb.GetItemOutput{}, nil) + + _, err := repo.GetByID("nonexistent-id") + assert.Error(t, err, "Expected error getting user") + + assert.Equal(t, "user not found", err.Error(), "Expected error message to be 'user not found'") + + mockDB.AssertExpectations(t) + }) + + t.Run("GetByID_Error", func(t *testing.T) { + mockDB := new(mocks.MockDynamoDB) + repo := NewUserRepositoryImpl(mockDB, "test-table") + + mockDB.On("GetItem", mock.Anything).Return(&dynamodb.GetItemOutput{}, errors.New("error getting user")) + + _, err := repo.GetByID("test-id") + assert.Error(t, err, "Expected error getting user") + + assert.Equal(t, "error getting user", err.Error(), "Expected error message to be 'error getting user'") + + mockDB.AssertExpectations(t) + }) + +} diff --git a/api-users/services/user_service_impl_test.go b/api-users/services/user_service_impl_test.go new file mode 100644 index 0000000..71a4884 --- /dev/null +++ b/api-users/services/user_service_impl_test.go @@ -0,0 +1,472 @@ +package services + +import ( + "errors" + "testing" + + "github.com/dieg0code/shared/json/request" + "github.com/dieg0code/shared/mocks" + "github.com/dieg0code/shared/models" + "github.com/go-playground/validator/v10" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" +) + +func TestUserServiceImpl_LogInUser(t *testing.T) { + t.Run("LogInUser_Success", func(t *testing.T) { + userRepo := new(mocks.MockUserRepository) + passwordHasher := new(mocks.MockPasswordHasher) + jwtUtils := new(mocks.MockJWTUtils) + validator := validator.New() + userService := NewUserServiceImpl(userRepo, validator, passwordHasher, jwtUtils) + + loginUserReq := request.LogInUserRequest{ + Email: "test@test.com", + Password: "password", + } + + user := models.User{ + UserID: "test-id", + Email: "test@test.com", + Username: "test", + Password: "password", + Role: "user", + } + + userRepo.On("GetByEmail", loginUserReq.Email).Return(user, nil) + passwordHasher.On("ComparePassword", user.Password, loginUserReq.Password).Return(nil) + + token := "test-token" + + jwtUtils.On("GenerateToken", user.UserID).Return(token, nil) + + logInUserResponse, err := userService.LogInUser(loginUserReq) + assert.NoError(t, err, "Expected no error login user") + + assert.Equal(t, token, logInUserResponse.Token, "Expected token to be equal") + + userRepo.AssertExpectations(t) + }) + + t.Run("LogInUser_InvalidRequest", func(t *testing.T) { + userRepo := new(mocks.MockUserRepository) + passwordHasher := new(mocks.MockPasswordHasher) + jwtUtils := new(mocks.MockJWTUtils) + validator := validator.New() + userService := NewUserServiceImpl(userRepo, validator, passwordHasher, jwtUtils) + + loginUserReq := request.LogInUserRequest{ + Email: "test@test.com", + Password: "", + } + + logInUserResponse, err := userService.LogInUser(loginUserReq) + + assert.Error(t, err, "Expected error login user") + assert.Empty(t, logInUserResponse, "Expected empty login user response") + + userRepo.AssertExpectations(t) + }) + + t.Run("LogInUser_GetByEmailError", func(t *testing.T) { + userRepo := new(mocks.MockUserRepository) + passwordHasher := new(mocks.MockPasswordHasher) + jwtUtils := new(mocks.MockJWTUtils) + validator := validator.New() + userService := NewUserServiceImpl(userRepo, validator, passwordHasher, jwtUtils) + + loginUserReq := request.LogInUserRequest{ + Email: "invalid-email@test.com", + Password: "password", + } + + userRepo.On("GetByEmail", loginUserReq.Email).Return(models.User{}, errors.New("error getting user by email")) + + logInUserResponse, err := userService.LogInUser(loginUserReq) + + assert.Error(t, err, "Expected error login user") + assert.Empty(t, logInUserResponse, "Expected empty login user response") + + userRepo.AssertExpectations(t) + }) + + t.Run("LogInUser_ComparePasswordError", func(t *testing.T) { + userRepo := new(mocks.MockUserRepository) + passwordHasher := new(mocks.MockPasswordHasher) + jwtUtils := new(mocks.MockJWTUtils) + validator := validator.New() + userService := NewUserServiceImpl(userRepo, validator, passwordHasher, jwtUtils) + + loginUserReq := request.LogInUserRequest{ + Email: "test@test.com", + Password: "wrong password", + } + + user := models.User{ + UserID: "test-id", + Email: "test@test.com", + Username: "test", + Password: "password", + Role: "user", + } + + userRepo.On("GetByEmail", loginUserReq.Email).Return(user, nil) + passwordHasher.On("ComparePassword", user.Password, loginUserReq.Password).Return(errors.New("error comparing password")) + + logInUserResponse, err := userService.LogInUser(loginUserReq) + + assert.Error(t, err, "Expected error login user") + assert.Equal(t, "invalid password", err.Error(), "Expected invalid password error") + assert.Empty(t, logInUserResponse, "Expected empty login user response") + + userRepo.AssertExpectations(t) + }) + + t.Run("LogInUser_GenerateTokenError", func(t *testing.T) { + userRepo := new(mocks.MockUserRepository) + passwordHasher := new(mocks.MockPasswordHasher) + jwtUtils := new(mocks.MockJWTUtils) + validator := validator.New() + userService := NewUserServiceImpl(userRepo, validator, passwordHasher, jwtUtils) + + loginUserReq := request.LogInUserRequest{ + Email: "test@test.com", + Password: "password", + } + + user := models.User{ + UserID: "test-id", + Email: "test@test.com", + Username: "test", + Password: "password", + Role: "user", + } + + userRepo.On("GetByEmail", loginUserReq.Email).Return(user, nil) + passwordHasher.On("ComparePassword", user.Password, loginUserReq.Password).Return(nil) + jwtUtils.On("GenerateToken", user.UserID).Return("", errors.New("error generating token")) + + logInUserResponse, err := userService.LogInUser(loginUserReq) + + assert.Error(t, err, "Expected error generating Token") + assert.Empty(t, logInUserResponse, "Expected empty login user response") + + userRepo.AssertExpectations(t) + + }) + + t.Run("LogInUser_InvalidResponse", func(t *testing.T) { + userRepo := new(mocks.MockUserRepository) + passwordHasher := new(mocks.MockPasswordHasher) + jwtUtils := new(mocks.MockJWTUtils) + validator := validator.New() + userService := NewUserServiceImpl(userRepo, validator, passwordHasher, jwtUtils) + + loginUserReq := request.LogInUserRequest{ + Email: "test@test.com", + Password: "password", + } + + user := models.User{ + UserID: "test-id", + Email: "test@test.com", + Username: "test", + Password: "password", + Role: "user", + } + + userRepo.On("GetByEmail", loginUserReq.Email).Return(user, nil) + passwordHasher.On("ComparePassword", user.Password, loginUserReq.Password).Return(nil) + jwtUtils.On("GenerateToken", user.UserID).Return("", nil) + + logInUserResponse, err := userService.LogInUser(loginUserReq) + + assert.Error(t, err, "Expected error validating login user response") + assert.Empty(t, logInUserResponse, "Expected empty login user response") + + userRepo.AssertExpectations(t) + + }) +} + +func TestUserServiceImpl_GetAllUsers(t *testing.T) { + + t.Run("GetAllUser_Success", func(t *testing.T) { + userRepo := new(mocks.MockUserRepository) + passwordHasher := new(mocks.MockPasswordHasher) + jwtUtils := new(mocks.MockJWTUtils) + validator := validator.New() + userService := NewUserServiceImpl(userRepo, validator, passwordHasher, jwtUtils) + + users := []models.User{ + { + UserID: "test-id", + Email: "test@test.com", + Username: "test", + Password: "test", + Role: "user", + }, + { + UserID: "test-id-1", + Email: "test2@test.com", + Username: "test2", + Password: "test2", + Role: "user", + }, + } + + userRepo.On("GetAll").Return(users, nil) + + userResponses, err := userService.GetAllUsers() + + assert.NoError(t, err, "Expected no error getting all users") + assert.Len(t, userResponses, 2, "Expected 2 user responses") + + userRepo.AssertExpectations(t) + }) + + t.Run("GetAllUser_Error", func(t *testing.T) { + userRepo := new(mocks.MockUserRepository) + passwordHasher := new(mocks.MockPasswordHasher) + jwtUtils := new(mocks.MockJWTUtils) + validator := validator.New() + + userService := NewUserServiceImpl(userRepo, validator, passwordHasher, jwtUtils) + + userRepo.On("GetAll").Return([]models.User{}, errors.New("error getting all users")) + + userResponses, err := userService.GetAllUsers() + + assert.Error(t, err, "Expected error getting all users") + assert.Nil(t, userResponses, "Expected nil user responses") + + userRepo.AssertExpectations(t) + }) + + t.Run("GetAllUser_InvalidResponse", func(t *testing.T) { + userRepo := new(mocks.MockUserRepository) + passwordHasher := new(mocks.MockPasswordHasher) + jwtUtils := new(mocks.MockJWTUtils) + validator := validator.New() + + userService := NewUserServiceImpl(userRepo, validator, passwordHasher, jwtUtils) + + users := []models.User{ + { + UserID: "test-id", + Email: "invalid-email", // Invalid email format + Username: "test", + Password: "test", + Role: "user", + }, + { + UserID: "test-id-1", + Email: "test2@test.com", + Username: "", // Empty username + Password: "test2", + Role: "user", + }, + } + + userRepo.On("GetAll").Return(users, nil) + + userResponses, err := userService.GetAllUsers() + + assert.Error(t, err, "Expected error validating user response") + assert.Nil(t, userResponses, "Expected nil user responses") + }) +} + +func TestUserServiceImpl_GetUserByID(t *testing.T) { + t.Run("GetUserByID_Success", func(t *testing.T) { + userRepo := new(mocks.MockUserRepository) + passwordHasher := new(mocks.MockPasswordHasher) + jwtUtils := new(mocks.MockJWTUtils) + validator := validator.New() + userService := NewUserServiceImpl(userRepo, validator, passwordHasher, jwtUtils) + + userID := "test-id" + + user := models.User{ + UserID: userID, + Email: "test@test.com", + Username: "test", + Password: "test", + Role: "user", + } + + userRepo.On("GetByID", userID).Return(user, nil) + + userResponse, err := userService.GetUserByID(userID) + + assert.NoError(t, err, "Expected no error getting user by id") + assert.Equal(t, user.UserID, userResponse.UserID, "Expected user id to be equal") + + userRepo.AssertExpectations(t) + + }) + + t.Run("GetUserByID_Error", func(t *testing.T) { + userRepo := new(mocks.MockUserRepository) + passwordHasher := new(mocks.MockPasswordHasher) + jwtUtils := new(mocks.MockJWTUtils) + validator := validator.New() + userService := NewUserServiceImpl(userRepo, validator, passwordHasher, jwtUtils) + + userID := "test-id" + + userRepo.On("GetByID", userID).Return(models.User{}, errors.New("error getting user by id")) + + userResponse, err := userService.GetUserByID(userID) + + assert.Error(t, err, "Expected error getting user by id") + assert.Empty(t, userResponse, "Expected empty user response") + + userRepo.AssertExpectations(t) + }) + + t.Run("GetUserByID_InvalidResponse", func(t *testing.T) { + userRepo := new(mocks.MockUserRepository) + passwordHasher := new(mocks.MockPasswordHasher) + jwtUtils := new(mocks.MockJWTUtils) + validator := validator.New() + userService := NewUserServiceImpl(userRepo, validator, passwordHasher, jwtUtils) + + userID := "test-id" + + user := models.User{ + UserID: userID, + Email: "invalid-email", // Invalid email format + Username: "test", + Password: "test", + Role: "user", + } + + userRepo.On("GetByID", userID).Return(user, nil) + + userResponse, err := userService.GetUserByID(userID) + + assert.Error(t, err, "Expected error validating user response") + assert.Empty(t, userResponse, "Expected empty user response") + + userRepo.AssertExpectations(t) + }) +} + +func TestUserServiceImpl_RegisterUser(t *testing.T) { + t.Run("RegisterUser_Success", func(t *testing.T) { + userRepo := new(mocks.MockUserRepository) + passwordHasher := new(mocks.MockPasswordHasher) + jwtUtils := new(mocks.MockJWTUtils) + validator := validator.New() + userService := NewUserServiceImpl(userRepo, validator, passwordHasher, jwtUtils) + + createUserReq := request.CreateUserRequest{ + Username: "test", + Email: "test@test.com", + Password: "password", + Role: "user", + } + + hashedPassword := "hashed-password" + + passwordHasher.On("HashPassword", createUserReq.Password).Return(hashedPassword, nil) + + userMatcher := mock.MatchedBy(func(user models.User) bool { + return user.Username == createUserReq.Username && + user.Email == createUserReq.Email && + user.Password == hashedPassword && + user.Role == createUserReq.Role + }) + + expectedUser := models.User{ + UserID: "test-id", + Username: createUserReq.Username, + Email: createUserReq.Email, + Password: hashedPassword, + Role: createUserReq.Role, + } + + userRepo.On("Create", userMatcher).Return(expectedUser, nil) + + registeredUser, err := userService.RegisterUser(createUserReq) + + assert.NoError(t, err, "Expected no error registering user") + assert.Equal(t, expectedUser.UserID, registeredUser.UserID, "Expected user id to be equal") + + userRepo.AssertExpectations(t) + }) + + t.Run("RegisterUser_InvalidRequest", func(t *testing.T) { + userRepo := new(mocks.MockUserRepository) + passwordHasher := new(mocks.MockPasswordHasher) + jwtUtils := new(mocks.MockJWTUtils) + validator := validator.New() + userService := NewUserServiceImpl(userRepo, validator, passwordHasher, jwtUtils) + + createUserReq := request.CreateUserRequest{ + Username: "test", + Email: "invalid-email", + Password: "password", + Role: "user", + } + + registeredUser, err := userService.RegisterUser(createUserReq) + + assert.Error(t, err, "Expected error registering user") + assert.Empty(t, registeredUser, "Expected empty registered user") + + userRepo.AssertExpectations(t) + }) + + t.Run("RegisterUser_HashPasswordError", func(t *testing.T) { + userRepo := new(mocks.MockUserRepository) + passwordHasher := new(mocks.MockPasswordHasher) + jwtUtils := new(mocks.MockJWTUtils) + validator := validator.New() + userService := NewUserServiceImpl(userRepo, validator, passwordHasher, jwtUtils) + + createUserReq := request.CreateUserRequest{ + Username: "test", + Email: "test@test.com", + Password: "password", + Role: "user", + } + + passwordHasher.On("HashPassword", createUserReq.Password).Return("", errors.New("error hashing password")) + + registeredUser, err := userService.RegisterUser(createUserReq) + + assert.Error(t, err, "Expected error hashing password") + assert.Empty(t, registeredUser, "Expected empty registered user") + + userRepo.AssertExpectations(t) + }) + + t.Run("RegisterUser_CreateUserError", func(t *testing.T) { + userRepo := new(mocks.MockUserRepository) + passwordHasher := new(mocks.MockPasswordHasher) + jwtUtils := new(mocks.MockJWTUtils) + validator := validator.New() + userService := NewUserServiceImpl(userRepo, validator, passwordHasher, jwtUtils) + + createUserReq := request.CreateUserRequest{ + Username: "test", + Email: "test@test.com", + Password: "password", + Role: "user", + } + + hashedPassword := "hashed-password" + + passwordHasher.On("HashPassword", createUserReq.Password).Return(hashedPassword, nil) + userRepo.On("Create", mock.Anything).Return(models.User{}, errors.New("error creating user")) + + registeredUser, err := userService.RegisterUser(createUserReq) + + assert.Error(t, err, "Expected error creating user") + assert.Empty(t, registeredUser, "Expected empty registered user") + + userRepo.AssertExpectations(t) + }) +}