From 5ff8413d265e2c076649a94a0eae52236db7542e Mon Sep 17 00:00:00 2001 From: RianIhsan Date: Wed, 1 Nov 2023 20:47:12 +0700 Subject: [PATCH] improvement:error handling and update unit test --- admin/mocks/Repository.go | 48 ++++++++++++++++++ admin/mocks/Service.go | 48 ++++++++++++++++++ admin/repository.go | 21 ++++++++ admin/service.go | 26 ++++++++++ admin/service_test.go | 101 ++++++++++++++++++++++++++++++++++++++ handler/admin.go | 21 ++++++-- 6 files changed, 261 insertions(+), 4 deletions(-) diff --git a/admin/mocks/Repository.go b/admin/mocks/Repository.go index eccad36..b75d989 100644 --- a/admin/mocks/Repository.go +++ b/admin/mocks/Repository.go @@ -16,6 +16,54 @@ type Repository struct { mock.Mock } +// FindCampaignById provides a mock function with given fields: id +func (_m *Repository) FindCampaignById(id int) (campaign.Campaign, error) { + ret := _m.Called(id) + + var r0 campaign.Campaign + var r1 error + if rf, ok := ret.Get(0).(func(int) (campaign.Campaign, error)); ok { + return rf(id) + } + if rf, ok := ret.Get(0).(func(int) campaign.Campaign); ok { + r0 = rf(id) + } else { + r0 = ret.Get(0).(campaign.Campaign) + } + + if rf, ok := ret.Get(1).(func(int) error); ok { + r1 = rf(id) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FindUserById provides a mock function with given fields: userId +func (_m *Repository) FindUserById(userId int) (user.User, error) { + ret := _m.Called(userId) + + var r0 user.User + var r1 error + if rf, ok := ret.Get(0).(func(int) (user.User, error)); ok { + return rf(userId) + } + if rf, ok := ret.Get(0).(func(int) user.User); ok { + r0 = rf(userId) + } else { + r0 = ret.Get(0).(user.User) + } + + if rf, ok := ret.Get(1).(func(int) error); ok { + r1 = rf(userId) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetCampaignById provides a mock function with given fields: campaignId func (_m *Repository) GetCampaignById(campaignId int) (campaign.Campaign, error) { ret := _m.Called(campaignId) diff --git a/admin/mocks/Service.go b/admin/mocks/Service.go index c6745d4..f345cda 100644 --- a/admin/mocks/Service.go +++ b/admin/mocks/Service.go @@ -64,6 +64,54 @@ func (_m *Service) DeleteUserById(id int) (user.User, error) { return r0, r1 } +// FindCampaignById provides a mock function with given fields: id +func (_m *Service) FindCampaignById(id int) (campaign.Campaign, error) { + ret := _m.Called(id) + + var r0 campaign.Campaign + var r1 error + if rf, ok := ret.Get(0).(func(int) (campaign.Campaign, error)); ok { + return rf(id) + } + if rf, ok := ret.Get(0).(func(int) campaign.Campaign); ok { + r0 = rf(id) + } else { + r0 = ret.Get(0).(campaign.Campaign) + } + + if rf, ok := ret.Get(1).(func(int) error); ok { + r1 = rf(id) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FindUserById provides a mock function with given fields: id +func (_m *Service) FindUserById(id int) (user.User, error) { + ret := _m.Called(id) + + var r0 user.User + var r1 error + if rf, ok := ret.Get(0).(func(int) (user.User, error)); ok { + return rf(id) + } + if rf, ok := ret.Get(0).(func(int) user.User); ok { + r0 = rf(id) + } else { + r0 = ret.Get(0).(user.User) + } + + if rf, ok := ret.Get(1).(func(int) error); ok { + r1 = rf(id) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetTransactionsPagination provides a mock function with given fields: page, pageSize func (_m *Service) GetTransactionsPagination(page int, pageSize int) ([]transaction.Transaction, int, int, int, int, error) { ret := _m.Called(page, pageSize) diff --git a/admin/repository.go b/admin/repository.go index fbada53..854a192 100644 --- a/admin/repository.go +++ b/admin/repository.go @@ -17,6 +17,8 @@ type Repository interface { GetTotalTransactionsByUsername(name string) (int64, error) GetUserById(userId int) (user.User, error) GetCampaignById(campaignId int) (campaign.Campaign, error) + FindUserById(userId int) (user.User, error) + FindCampaignById(id int) (campaign.Campaign, error) } type repository struct { @@ -103,6 +105,15 @@ func (r *repository) GetUserById(userId int) (user.User, error) { return u, nil } +func (r *repository) FindUserById(ID int) (user.User, error) { + var u user.User + err := r.db.Where("id = ?", ID).Find(&u).Error + if err != nil { + return u, err + } + return u, err +} + func (r *repository) GetCampaignById(campaignId int) (campaign.Campaign, error) { var c campaign.Campaign err := r.db.Where("id = ?", campaignId).Delete(&c).Error @@ -112,3 +123,13 @@ func (r *repository) GetCampaignById(campaignId int) (campaign.Campaign, error) return c, nil } + +func (r *repository) FindCampaignById(id int) (campaign.Campaign, error) { + var c campaign.Campaign + err := r.db.Where("id = ?", id).Find(&c).Error + if err != nil { + return c, err + } + + return c, nil +} diff --git a/admin/service.go b/admin/service.go index 7557e75..5f4064b 100644 --- a/admin/service.go +++ b/admin/service.go @@ -1,6 +1,7 @@ package admin import ( + "errors" "github.com/RianIhsan/raise-unity/campaign" "github.com/RianIhsan/raise-unity/transaction" "github.com/RianIhsan/raise-unity/user" @@ -14,6 +15,8 @@ type Service interface { SearchTransactionByUsername(name string) ([]transaction.Transaction, error) DeleteUserById(id int) (user.User, error) DeleteCampaignById(id int) (campaign.Campaign, error) + FindUserById(id int) (user.User, error) + FindCampaignById(id int) (campaign.Campaign, error) } type service struct { @@ -94,6 +97,18 @@ func (s *service) SearchTransactionByUsername(name string) ([]transaction.Transa return userTransaction, nil } +func (s *service) FindUserById(id int) (user.User, error) { + user, err := s.repository.FindUserById(id) + if err != nil { + return user, err + } + if user.ID == 0 { + return user, errors.New("no user found with that ID") + } + + return user, err +} + func (s *service) DeleteUserById(id int) (user.User, error) { deleteUser, err := s.repository.GetUserById(id) if err != nil { @@ -110,3 +125,14 @@ func (s *service) DeleteCampaignById(id int) (campaign.Campaign, error) { } return deleteCampaign, err } + +func (s *service) FindCampaignById(id int) (campaign.Campaign, error) { + campaign, err := s.repository.FindCampaignById(id) + if err != nil { + return campaign, err + } + if campaign.ID == 0 { + return campaign, errors.New("no campaign found with that id") + } + return campaign, nil +} diff --git a/admin/service_test.go b/admin/service_test.go index 6f0bfb2..0634e45 100644 --- a/admin/service_test.go +++ b/admin/service_test.go @@ -414,6 +414,7 @@ func TestDeleteUserById(t *testing.T) { result, err := service.DeleteUserById(user.ID) assert.NoError(t, err) assert.Equal(t, user.ID, result.ID) + repository.AssertExpectations(t) }) @@ -423,6 +424,8 @@ func TestDeleteUserById(t *testing.T) { _, err := service.DeleteUserById(user.ID) assert.Error(t, err) assert.Equal(t, "User not found", err.Error()) + repository.AssertExpectations(t) + }) } @@ -479,5 +482,103 @@ func TestDeleteCampaignId(t *testing.T) { _, err := service.DeleteCampaignById(MockCampaign.ID) assert.Error(t, err) assert.Equal(t, "Campaign not found", err.Error()) + repository.AssertExpectations(t) + }) } + +func TestFindUserById(t *testing.T) { + var repository = mocks.NewRepository(t) + var service = NewService(repository) + + mockUser := user.User{ + ID: 1, + Name: "Rian", + Occupation: "programmer", + Email: "rianganteng@gmail.com", + Password: "rian12345", + Avatar: "www.cloudinary.com/avatar", + Role: "user", + IsVerified: true, + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + } + + t.Run("Success get user id", func(t *testing.T) { + repository.On("FindUserById", mockUser.ID).Return(mockUser, nil).Once() + result, err := service.FindUserById(mockUser.ID) + assert.NoError(t, err) + assert.Equal(t, mockUser.ID, result.ID) + repository.AssertExpectations(t) + + }) + + t.Run("Failed get user id", func(t *testing.T) { + repository.On("FindUserById", mockUser.ID).Return(mockUser, errors.New("no user found with that ID")).Once() + _, err := service.FindUserById(mockUser.ID) + assert.Error(t, err) + assert.Equal(t, 1, mockUser.ID, "no user found with that ID") + repository.AssertExpectations(t) + }) + +} + +func TestFindCampaignById(t *testing.T) { + var repository = mocks.NewRepository(t) + var service = NewService(repository) + + mockCampaign := campaign.Campaign{ + ID: 1, + UserID: 1, + Name: "Sample Campaign", + ShortDescription: "A short description", + Description: "A long description", + Perks: "Perks for backers", + BackerCount: 100, + GoalAmount: 10000, + CurrentAmount: 5000, + Status: "active", + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + CampaignImages: []campaign.CampaignImage{ + { + ID: 1, + CampaignID: 1, + IsPrimary: 1, + FileName: "gambar.png", + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + }, + }, + User: user.User{ + ID: 1, + Name: "Rian", + Occupation: "programmer", + Email: "rianganteng@gmail.com", + Password: "rian12345", + Avatar: "www.cloudinary.com/avatar", + Role: "user", + IsVerified: true, + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + }, + } + + t.Run("Success get campaign id", func(t *testing.T) { + repository.On("FindCampaignById", mockCampaign.ID).Return(mockCampaign, nil).Once() + result, err := service.FindCampaignById(mockCampaign.ID) + assert.NoError(t, err) + assert.Equal(t, mockCampaign.ID, result.ID) + repository.AssertExpectations(t) + + }) + + t.Run("Failed get campaign id", func(t *testing.T) { + repository.On("FindCampaignById", mockCampaign.ID).Return(mockCampaign, errors.New("no campaign found with that id")).Once() + _, err := service.FindCampaignById(mockCampaign.ID) + assert.Error(t, err) + assert.Equal(t, 1, mockCampaign.ID, "no campaign found with that id") + repository.AssertExpectations(t) + }) + +} diff --git a/handler/admin.go b/handler/admin.go index 229d2cf..757192a 100644 --- a/handler/admin.go +++ b/handler/admin.go @@ -124,15 +124,21 @@ func (h *adminHandler) DeleteUser(c *gin.Context) { c.JSON(http.StatusBadRequest, response) return } + user, err := h.service.FindUserById(userId) + if err != nil { + response := helper.ErrorResponse("Failed get user", err.Error()) + c.JSON(http.StatusBadRequest, response) + return + } - _, err = h.service.DeleteUserById(userId) + _, err = h.service.DeleteUserById(user.ID) if err != nil { response := helper.ErrorResponse("Failed delete user", err.Error()) c.JSON(http.StatusBadRequest, response) return } - response := helper.GeneralResponse("Success Delete user") + response := helper.SuccesResponse("Success Delete user") c.JSON(http.StatusOK, response) } @@ -143,14 +149,21 @@ func (h *adminHandler) DeleteCampaign(c *gin.Context) { c.JSON(http.StatusUnauthorized, response) return } - campaignId, err := strconv.Atoi(c.Param("id")) + campaign, err := strconv.Atoi(c.Param("id")) + if err != nil { + response := helper.ErrorResponse("Failed get campaign", err.Error()) + c.JSON(http.StatusBadRequest, response) + return + } + + campaignId, err := h.service.FindCampaignById(campaign) if err != nil { response := helper.ErrorResponse("Failed get campaign", err.Error()) c.JSON(http.StatusBadRequest, response) return } - _, err = h.service.DeleteCampaignById(campaignId) + _, err = h.service.DeleteCampaignById(campaignId.ID) if err != nil { response := helper.ErrorResponse("Failed delete campaign", err.Error()) c.JSON(http.StatusBadRequest, response)