查看计划简单信息和单测
This commit is contained in:
@@ -14,11 +14,11 @@ import (
|
||||
func setupTestDB(t *testing.T) *gorm.DB {
|
||||
// "file::memory:?cache=shared" 是 GORM 连接内存 SQLite 的标准方式,确保在同一测试中的不同连接可以访问相同的数据。
|
||||
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{})
|
||||
assert.NoError(t, err, "数据库迁移不应出错")
|
||||
err = db.AutoMigrate(&models.User{}, &models.Device{}, &models.SubPlan{}, &models.Task{}, &models.Plan{})
|
||||
assert.NoError(t, err, "数据库迁移时发生错误")
|
||||
|
||||
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