查看计划简单信息和单测
This commit is contained in:
		| @@ -14,11 +14,11 @@ import ( | |||||||
| func setupTestDB(t *testing.T) *gorm.DB { | func setupTestDB(t *testing.T) *gorm.DB { | ||||||
| 	// "file::memory:?cache=shared" 是 GORM 连接内存 SQLite 的标准方式,确保在同一测试中的不同连接可以访问相同的数据。 | 	// "file::memory:?cache=shared" 是 GORM 连接内存 SQLite 的标准方式,确保在同一测试中的不同连接可以访问相同的数据。 | ||||||
| 	db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{}) | 	db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{}) | ||||||
| 	assert.NoError(t, err, "连接内存数据库不应出错") | 	assert.NoError(t, err, "连接内存数据库时发生错误") | ||||||
|  |  | ||||||
| 	// 自动迁移所有需要的表结构 | 	// 自动迁移所有需要的表结构 | ||||||
| 	err = db.AutoMigrate(&models.User{}, &models.Device{}) | 	err = db.AutoMigrate(&models.User{}, &models.Device{}, &models.SubPlan{}, &models.Task{}, &models.Plan{}) | ||||||
| 	assert.NoError(t, err, "数据库迁移不应出错") | 	assert.NoError(t, err, "数据库迁移时发生错误") | ||||||
|  |  | ||||||
| 	return db | 	return db | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										49
									
								
								internal/infra/repository/plan_repository.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								internal/infra/repository/plan_repository.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | |||||||
|  | package repository | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"git.huangwc.com/pig/pig-farm-controller/internal/infra/models" | ||||||
|  | 	"gorm.io/gorm" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // PlanRepository 定义了与计划模型相关的数据库操作接口 | ||||||
|  | // 这是为了让业务逻辑层依赖于抽象,而不是具体的数据库实现 | ||||||
|  | type PlanRepository interface { | ||||||
|  | 	// ListBasicPlans 获取所有计划的基本信息,不包含子计划和任务详情 | ||||||
|  | 	ListBasicPlans() ([]models.Plan, error) | ||||||
|  | 	// GetBasicPlanByID 根据ID获取计划的基本信息,不包含子计划和任务详情 | ||||||
|  | 	GetBasicPlanByID(id uint) (*models.Plan, error) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // gormPlanRepository 是 PlanRepository 的 GORM 实现 | ||||||
|  | type gormPlanRepository struct { | ||||||
|  | 	db *gorm.DB | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // NewGormPlanRepository 创建一个新的 PlanRepository GORM 实现实例 | ||||||
|  | func NewGormPlanRepository(db *gorm.DB) PlanRepository { | ||||||
|  | 	return &gormPlanRepository{ | ||||||
|  | 		db: db, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ListBasicPlans 获取所有计划的基本信息,不包含子计划和任务详情 | ||||||
|  | func (r *gormPlanRepository) ListBasicPlans() ([]models.Plan, error) { | ||||||
|  | 	var plans []models.Plan | ||||||
|  | 	// GORM 默认不会加载关联,除非使用 Preload,所以直接 Find 即可满足要求 | ||||||
|  | 	result := r.db.Find(&plans) | ||||||
|  | 	if result.Error != nil { | ||||||
|  | 		return nil, result.Error | ||||||
|  | 	} | ||||||
|  | 	return plans, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // GetBasicPlanByID 根据ID获取计划的基本信息,不包含子计划和任务详情 | ||||||
|  | func (r *gormPlanRepository) GetBasicPlanByID(id uint) (*models.Plan, error) { | ||||||
|  | 	var plan models.Plan | ||||||
|  | 	// GORM 默认不会加载关联,除非使用 Preload,所以直接 First 即可满足要求 | ||||||
|  | 	result := r.db.First(&plan, id) | ||||||
|  | 	if result.Error != nil { | ||||||
|  | 		return nil, result.Error | ||||||
|  | 	} | ||||||
|  | 	return &plan, nil | ||||||
|  | } | ||||||
							
								
								
									
										136
									
								
								internal/infra/repository/plan_repository_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								internal/infra/repository/plan_repository_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,136 @@ | |||||||
|  | package repository_test | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"errors" | ||||||
|  | 	"testing" | ||||||
|  |  | ||||||
|  | 	"git.huangwc.com/pig/pig-farm-controller/internal/infra/models" | ||||||
|  | 	"git.huangwc.com/pig/pig-farm-controller/internal/infra/repository" | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
|  | 	"gorm.io/gorm" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // createTestPlan 是一个辅助函数,用于创建测试计划。 | ||||||
|  | func createTestPlan(name, description string, execType models.PlanExecutionType, contentType models.PlanContentType) models.Plan { | ||||||
|  | 	return models.Plan{ | ||||||
|  | 		Name:          name, | ||||||
|  | 		Description:   description, | ||||||
|  | 		ExecutionType: execType, | ||||||
|  | 		ContentType:   contentType, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // TestListBasicPlans 测试 ListBasicPlans 方法,确保它能正确返回所有计划的基本信息。 | ||||||
|  | func TestListBasicPlans(t *testing.T) { | ||||||
|  | 	tests := []struct { | ||||||
|  | 		name          string | ||||||
|  | 		setupPlans    []models.Plan | ||||||
|  | 		expectedCount int | ||||||
|  | 		expectedError error | ||||||
|  | 	}{ | ||||||
|  | 		{ | ||||||
|  | 			name:          "数据库中没有计划", | ||||||
|  | 			setupPlans:    []models.Plan{}, | ||||||
|  | 			expectedCount: 0, | ||||||
|  | 			expectedError: nil, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name: "数据库中有多个计划", | ||||||
|  | 			setupPlans: []models.Plan{ | ||||||
|  | 				createTestPlan("计划 A", "描述 A", models.PlanExecutionTypeAutomatic, models.PlanContentTypeTasks), | ||||||
|  | 				createTestPlan("计划 B", "描述 B", models.PlanExecutionTypeManual, models.PlanContentTypeSubPlans), | ||||||
|  | 			}, | ||||||
|  | 			expectedCount: 2, | ||||||
|  | 			expectedError: nil, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, tt := range tests { | ||||||
|  | 		t.Run(tt.name, func(t *testing.T) { | ||||||
|  | 			db := setupTestDB(t) | ||||||
|  | 			repo := repository.NewGormPlanRepository(db) | ||||||
|  |  | ||||||
|  | 			for i := range tt.setupPlans { | ||||||
|  | 				err := db.Create(&tt.setupPlans[i]).Error | ||||||
|  | 				assert.NoError(t, err, "插入设置计划失败") | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			plans, err := repo.ListBasicPlans() | ||||||
|  |  | ||||||
|  | 			if tt.expectedError != nil { | ||||||
|  | 				assert.Error(t, err) | ||||||
|  | 				assert.True(t, errors.Is(err, tt.expectedError)) | ||||||
|  | 			} else { | ||||||
|  | 				assert.NoError(t, err) | ||||||
|  | 				assert.Len(t, plans, tt.expectedCount) | ||||||
|  | 				if tt.expectedCount > 0 { | ||||||
|  | 					// 验证返回的计划是否包含预期的ID | ||||||
|  | 					var actualIDs []uint | ||||||
|  | 					for _, p := range plans { | ||||||
|  | 						actualIDs = append(actualIDs, p.ID) | ||||||
|  | 						assert.Empty(t, p.SubPlans, "ListBasicPlans 不应加载子计划") | ||||||
|  | 						assert.Empty(t, p.Tasks, "ListBasicPlans 不应加载任务") | ||||||
|  | 					} | ||||||
|  | 					for _, setupPlan := range tt.setupPlans { | ||||||
|  | 						assert.Contains(t, actualIDs, setupPlan.ID, "返回的计划应包含设置计划的ID") | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // TestGetBasicPlanByID 测试 GetBasicPlanByID 方法,确保它能根据ID正确返回计划的基本信息。 | ||||||
|  | func TestGetBasicPlanByID(t *testing.T) { | ||||||
|  | 	tests := []struct { | ||||||
|  | 		name          string | ||||||
|  | 		setupPlan     models.Plan | ||||||
|  | 		idToFetch     uint | ||||||
|  | 		expectFound   bool | ||||||
|  | 		expectedError error | ||||||
|  | 	}{ | ||||||
|  | 		{ | ||||||
|  | 			name:        "通过ID找到计划", | ||||||
|  | 			setupPlan:   createTestPlan("计划 C", "描述 C", models.PlanExecutionTypeAutomatic, models.PlanContentTypeTasks), | ||||||
|  | 			idToFetch:   0, // 创建后设置 | ||||||
|  | 			expectFound: true, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name:          "通过ID未找到计划", | ||||||
|  | 			setupPlan:     models.Plan{}, // 此情况下无需设置计划 | ||||||
|  | 			idToFetch:     999, | ||||||
|  | 			expectFound:   false, | ||||||
|  | 			expectedError: gorm.ErrRecordNotFound, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, tt := range tests { | ||||||
|  | 		t.Run(tt.name, func(t *testing.T) { | ||||||
|  | 			db := setupTestDB(t) | ||||||
|  | 			repo := repository.NewGormPlanRepository(db) | ||||||
|  |  | ||||||
|  | 			if tt.setupPlan.Name != "" { // 仅在有效设置时创建计划 | ||||||
|  | 				err := db.Create(&tt.setupPlan).Error | ||||||
|  | 				assert.NoError(t, err, "插入设置计划失败") | ||||||
|  | 				tt.idToFetch = tt.setupPlan.ID // 使用数据库生成的ID | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			fetchedPlan, err := repo.GetBasicPlanByID(tt.idToFetch) | ||||||
|  |  | ||||||
|  | 			if tt.expectedError != nil { | ||||||
|  | 				assert.Error(t, err) | ||||||
|  | 				assert.True(t, errors.Is(err, tt.expectedError), "预期错误类型不匹配") | ||||||
|  | 				assert.Nil(t, fetchedPlan) | ||||||
|  | 			} else { | ||||||
|  | 				assert.NoError(t, err) | ||||||
|  | 				assert.NotNil(t, fetchedPlan) | ||||||
|  | 				assert.Equal(t, tt.setupPlan.Name, fetchedPlan.Name) | ||||||
|  | 				assert.Equal(t, tt.setupPlan.Description, fetchedPlan.Description) | ||||||
|  | 				assert.Equal(t, tt.setupPlan.ExecutionType, fetchedPlan.ExecutionType) | ||||||
|  | 				assert.Equal(t, tt.setupPlan.ContentType, fetchedPlan.ContentType) | ||||||
|  | 				assert.Empty(t, fetchedPlan.SubPlans, "GetBasicPlanByID 不应加载子计划") | ||||||
|  | 				assert.Empty(t, fetchedPlan.Tasks, "GetBasicPlanByID 不应加载任务") | ||||||
|  | 			} | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user