♻️ Refactoring configuration migration service
This commit is contained in:
167
internal/services/config_migrator_test.go
Normal file
167
internal/services/config_migrator_test.go
Normal file
@@ -0,0 +1,167 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
jsonparser "github.com/knadh/koanf/parsers/json"
|
||||
"github.com/knadh/koanf/providers/file"
|
||||
"github.com/knadh/koanf/v2"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/wailsapp/wails/v3/pkg/services/log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestConfig represents a simplified config structure for testing
|
||||
type TestConfig struct {
|
||||
App struct {
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
Theme string `json:"theme"`
|
||||
} `json:"app"`
|
||||
User struct {
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
Settings struct {
|
||||
AutoSave bool `json:"autoSave"`
|
||||
Language string `json:"language"`
|
||||
NewSetting bool `json:"newSetting"` // This field will be missing in old config
|
||||
NewSetting2 string `json:"newSetting2"` // This field will be missing in old config
|
||||
} `json:"settings"`
|
||||
} `json:"user"`
|
||||
NewSection struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
Value string `json:"value"`
|
||||
} `json:"newSection"` // This entire section will be missing in old config
|
||||
}
|
||||
|
||||
// createTestConfig creates a test configuration file
|
||||
func createTestConfig(t *testing.T, tempDir string) string {
|
||||
// Old config without some fields
|
||||
oldConfig := map[string]interface{}{
|
||||
"app": map[string]interface{}{
|
||||
"name": "TestApp",
|
||||
"version": "1.0.0",
|
||||
"theme": "dark",
|
||||
},
|
||||
"user": map[string]interface{}{
|
||||
"name": "Test User",
|
||||
"email": "test@example.com",
|
||||
"settings": map[string]interface{}{
|
||||
"autoSave": true,
|
||||
"language": "en",
|
||||
// Missing newSetting and newSetting2
|
||||
},
|
||||
},
|
||||
// Missing newSection
|
||||
}
|
||||
|
||||
// Create config file
|
||||
configPath := filepath.Join(tempDir, "config.json")
|
||||
jsonData, err := json.MarshalIndent(oldConfig, "", " ")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to marshal test config: %v", err)
|
||||
}
|
||||
|
||||
err = os.WriteFile(configPath, jsonData, 0644)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to write test config: %v", err)
|
||||
}
|
||||
|
||||
return configPath
|
||||
}
|
||||
|
||||
// TestConfigMigrator_AutoMigrate tests the ConfigMigrator's AutoMigrate functionality
|
||||
func TestConfigMigrator_AutoMigrate(t *testing.T) {
|
||||
// Create temp directory for test
|
||||
tempDir, err := os.MkdirTemp("", "config_migrator_test")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create temp directory: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tempDir)
|
||||
|
||||
// Create test config file
|
||||
configPath := createTestConfig(t, tempDir)
|
||||
|
||||
// Create logger
|
||||
logger := log.New()
|
||||
|
||||
// Create config migrator
|
||||
migrator := NewConfigMigrator(logger, tempDir, "config", configPath)
|
||||
|
||||
// Create koanf instance and load the config
|
||||
k := koanf.New(".")
|
||||
fileProvider := file.Provider(configPath)
|
||||
jsonParser := jsonparser.Parser()
|
||||
if err := k.Load(fileProvider, jsonParser); err != nil {
|
||||
t.Fatalf("Failed to load config: %v", err)
|
||||
}
|
||||
|
||||
// Create default config with all fields
|
||||
defaultConfig := TestConfig{}
|
||||
defaultConfig.App.Name = "TestApp"
|
||||
defaultConfig.App.Version = "1.0.0"
|
||||
defaultConfig.App.Theme = "dark"
|
||||
defaultConfig.User.Name = "Test User"
|
||||
defaultConfig.User.Email = "test@example.com"
|
||||
defaultConfig.User.Settings.AutoSave = true
|
||||
defaultConfig.User.Settings.Language = "en"
|
||||
defaultConfig.User.Settings.NewSetting = true // New field
|
||||
defaultConfig.User.Settings.NewSetting2 = "value" // New field
|
||||
defaultConfig.NewSection.Enabled = true // New section
|
||||
defaultConfig.NewSection.Value = "new section" // New section
|
||||
|
||||
// Run auto migration
|
||||
result, err := migrator.AutoMigrate(defaultConfig, k)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to auto migrate: %v", err)
|
||||
}
|
||||
|
||||
// Assertions
|
||||
assert.True(t, result.Migrated, "Migration should have been performed")
|
||||
|
||||
// 打印检测到的缺失字段,便于分析
|
||||
t.Logf("Detected fields: %v", result.MissingFields)
|
||||
|
||||
// 验证检测到了正确数量的字段 - 实际检测到4个
|
||||
assert.Equal(t, 4, len(result.MissingFields), "Should have detected 4 missing fields")
|
||||
|
||||
// 期望检测到的缺失字段
|
||||
expectedFields := map[string]bool{
|
||||
"user.settings.newSetting": true,
|
||||
"user.settings.newSetting2": true,
|
||||
"newSection.enabled": true,
|
||||
"newSection.value": true,
|
||||
}
|
||||
|
||||
// 验证所有预期的字段都被检测到了
|
||||
for _, field := range result.MissingFields {
|
||||
_, expected := expectedFields[field]
|
||||
assert.True(t, expected, "Field %s was detected but not expected", field)
|
||||
}
|
||||
|
||||
// 验证所有检测到的字段都在预期之内
|
||||
for expectedField := range expectedFields {
|
||||
found := false
|
||||
for _, field := range result.MissingFields {
|
||||
if field == expectedField {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.True(t, found, "Expected field %s was not detected", expectedField)
|
||||
}
|
||||
|
||||
// Verify that the fields were actually added to the config
|
||||
assert.True(t, k.Bool("user.settings.newSetting"), "newSetting should be added with correct value")
|
||||
assert.Equal(t, "value", k.String("user.settings.newSetting2"), "newSetting2 should be added with correct value")
|
||||
assert.True(t, k.Bool("newSection.enabled"), "newSection.enabled should be added with correct value")
|
||||
assert.Equal(t, "new section", k.String("newSection.value"), "newSection.value should be added with correct value")
|
||||
|
||||
// Check that backup was created
|
||||
backupFiles, err := filepath.Glob(filepath.Join(tempDir, "*.backup.*"))
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to list backup files: %v", err)
|
||||
}
|
||||
assert.Equal(t, 1, len(backupFiles), "One backup file should have been created")
|
||||
}
|
||||
Reference in New Issue
Block a user