package usecase import ( "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/usecase" "code.30cm.net/digimon/library-go/errs" "context" "errors" "github.com/stretchr/testify/assert" "github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/stores/mon" "go.mongodb.org/mongo-driver/bson/primitive" "go.uber.org/mock/gomock" "testing" mockRepository "code.30cm.net/digimon/app-cloudep-product-service/pkg/mock/repository" ) func TestCategoryUseCase_FindOneByID(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() mockCategoryRepo := mockRepository.NewMockCategoryRepository(mockCtrl) useCase := MustCategoryUseCase(CategoryUseCaseParam{ CategoryRepo: mockCategoryRepo, }) ctx := context.Background() id := primitive.NewObjectID() tests := []struct { name string id primitive.ObjectID mockSetup func() expectedError error expectedResult *entity.Category }{ { name: "成功找到 Category", id: id, mockSetup: func() { mockCategoryRepo.EXPECT().FindOneByID(ctx, id.Hex()).Return(&entity.Category{ ID: id, Name: "Test Category", }, nil) }, expectedError: nil, expectedResult: &entity.Category{ ID: id, Name: "Test Category", }, }, { name: "Category 不存在", id: primitive.NewObjectID(), mockSetup: func() { mockCategoryRepo.EXPECT().FindOneByID(ctx, gomock.Any()).Return(nil, mon.ErrNotFound) }, expectedError: errs.ResourceNotFound("failed to get category"), expectedResult: nil, }, { name: "資料庫錯誤", id: primitive.NewObjectID(), mockSetup: func() { mockCategoryRepo.EXPECT().FindOneByID(ctx, gomock.Any()).Return(nil, errors.New("database error")) }, expectedError: errs.DBErrorL( logx.WithContext(ctx), []logx.LogField{ {Key: "req", Value: "db_error_id"}, {Key: "func", Value: "CategoryRepo.FindOneByID"}, {Key: "err", Value: "database error"}, }, "failed to get category").Wrap(errors.New("database error")), expectedResult: nil, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.mockSetup() result, err := useCase.FindOneByID(ctx, tt.id.Hex()) if tt.expectedError == nil { assert.NoError(t, err) assert.Equal(t, tt.expectedResult, result) } else { assert.Error(t, err) assert.Equal(t, tt.expectedError.Error(), err.Error()) assert.Nil(t, result) } }) } } func TestCategoryUseCase_Update(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() mockCategoryRepo := mockRepository.NewMockCategoryRepository(mockCtrl) useCase := MustCategoryUseCase(CategoryUseCaseParam{ CategoryRepo: mockCategoryRepo, }) ctx := context.Background() tests := []struct { name string id string data entity.Category mockSetup func() expectedError error }{ { name: "成功更新 Category", id: "valid_id", data: entity.Category{ Name: "Updated Category", }, mockSetup: func() { mockCategoryRepo.EXPECT().Update(ctx, "valid_id", &entity.Category{ Name: "Updated Category", }).Return(nil, nil) }, expectedError: nil, }, { name: "Category 不存在", id: "non_existing_id", data: entity.Category{ Name: "Non-existing Category", }, mockSetup: func() { mockCategoryRepo.EXPECT().Update(ctx, "non_existing_id", &entity.Category{ Name: "Non-existing Category", }).Return(nil, mon.ErrNotFound) }, expectedError: errs.ResourceNotFound( "failed to update category", ), }, { name: "資料庫錯誤", id: "db_error_id", data: entity.Category{ Name: "DB Error Category", }, mockSetup: func() { mockCategoryRepo.EXPECT().Update(ctx, "db_error_id", &entity.Category{ Name: "DB Error Category", }).Return(nil, errors.New("database error")) }, expectedError: errs.DBErrorL( logx.WithContext(ctx), []logx.LogField{ {Key: "req", Value: "db_error_id"}, {Key: "func", Value: "CategoryRepo.Update"}, {Key: "err", Value: "database error"}, }, "failed to update category").Wrap(errors.New("database error")), }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.mockSetup() // 執行測試方法 err := useCase.Update(ctx, tt.id, &tt.data) // 驗證結果 if tt.expectedError == nil { assert.NoError(t, err) } else { assert.Error(t, err) assert.Equal(t, tt.expectedError.Error(), err.Error()) } }) } } func TestCategoryUseCase_Insert(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() mockCategoryRepo := mockRepository.NewMockCategoryRepository(mockCtrl) useCase := MustCategoryUseCase(CategoryUseCaseParam{ CategoryRepo: mockCategoryRepo, }) ctx := context.Background() tests := []struct { name string input entity.Category mockSetup func() expectedError error }{ { name: "成功插入 Category", input: entity.Category{ Name: "Test Category", }, mockSetup: func() { mockCategoryRepo.EXPECT().Insert(ctx, &entity.Category{ Name: "Test Category", }).Return(nil) }, expectedError: nil, }, { name: "插入失敗 - Database Error", input: entity.Category{ Name: "Invalid Category", }, mockSetup: func() { mockCategoryRepo.EXPECT().Insert(ctx, &entity.Category{ Name: "Invalid Category", }).Return(errors.New("database connection error")) }, expectedError: errs.DBErrorL( logx.WithContext(ctx), []logx.LogField{ {Key: "req", Value: entity.Category{Name: "Invalid Category"}}, {Key: "func", Value: "CategoryRepo.Insert"}, {Key: "err", Value: "database connection error"}, }, "failed to create category", ).Wrap(errors.New("database connection error")), }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.mockSetup() // 執行測試方法 err := useCase.Insert(ctx, &tt.input) // 驗證結果 if tt.expectedError == nil { assert.NoError(t, err) } else { assert.Error(t, err) assert.Equal(t, tt.expectedError.Error(), err.Error()) } }) } } func TestCategoryUseCase_Delete(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() mockCategoryRepo := mockRepository.NewMockCategoryRepository(mockCtrl) useCase := MustCategoryUseCase(CategoryUseCaseParam{ CategoryRepo: mockCategoryRepo, }) ctx := context.Background() tests := []struct { name string id string mockSetup func() expectedError error }{ { name: "成功刪除 Category", id: "valid_id", mockSetup: func() { mockCategoryRepo.EXPECT().Delete(ctx, gomock.Any()).Return(int64(1), nil) }, expectedError: nil, }, { name: "資料庫錯誤", id: "db_error_id", mockSetup: func() { mockCategoryRepo.EXPECT().Delete(ctx, gomock.Any()).Return(int64(0), errors.New("database error")) }, expectedError: errs.DBErrorL( logx.WithContext(ctx), []logx.LogField{ {Key: "req", Value: "db_error_id"}, {Key: "func", Value: "CategoryRepo.Delete"}, {Key: "err", Value: "database error"}, }, "failed to delete category").Wrap(errors.New("database error")), }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.mockSetup() // 執行測試方法 err := useCase.Delete(ctx, tt.id) // 驗證結果 if tt.expectedError == nil { assert.NoError(t, err) } else { assert.Error(t, err) assert.Equal(t, tt.expectedError.Error(), err.Error()) } }) } } func TestCategoryUseCase_ListCategory(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() mockCategoryRepo := mockRepository.NewMockCategoryRepository(mockCtrl) useCase := MustCategoryUseCase(CategoryUseCaseParam{ CategoryRepo: mockCategoryRepo, }) ctx := context.Background() id := primitive.NewObjectID() tests := []struct { name string params usecase.CategoryQueryParams mockSetup func() expectedResult []*entity.Category expectedCount int64 expectedError error }{ { name: "成功列出 Category", params: usecase.CategoryQueryParams{ ID: []string{id.Hex()}, PageIndex: 1, PageSize: 10, }, mockSetup: func() { mockCategoryRepo.EXPECT().ListCategory(ctx, &repository.CategoryQueryParams{ ID: []string{id.Hex()}, PageIndex: 1, PageSize: 10, }).Return([]*entity.Category{ { ID: id, Name: "Test Category", }, }, int64(1), nil) }, expectedResult: []*entity.Category{ { ID: id, Name: "Test Category", }, }, expectedCount: int64(1), expectedError: nil, }, { name: "資料庫錯誤", params: usecase.CategoryQueryParams{ ID: []string{"db_error_id"}, PageIndex: 1, PageSize: 10, }, mockSetup: func() { mockCategoryRepo.EXPECT().ListCategory(ctx, &repository.CategoryQueryParams{ ID: []string{"db_error_id"}, PageIndex: 1, PageSize: 10, }).Return(nil, int64(0), errors.New("database error")) }, expectedResult: nil, expectedCount: int64(0), expectedError: errs.DBErrorL( logx.WithContext(ctx), []logx.LogField{ {Key: "req", Value: usecase.CategoryQueryParams{ ID: []string{"db_error_id"}, PageIndex: 1, PageSize: 10, }}, {Key: "func", Value: "CategoryRepo.ListCategory"}, {Key: "err", Value: "database error"}, }, "failed to list category").Wrap(errors.New("database error")), }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.mockSetup() // 執行測試方法 result, count, err := useCase.ListCategory(ctx, tt.params) // 驗證結果 assert.Equal(t, tt.expectedResult, result) assert.Equal(t, tt.expectedCount, count) if tt.expectedError == nil { assert.NoError(t, err) } else { assert.Error(t, err) assert.Equal(t, tt.expectedError.Error(), err.Error()) } }) } }