feat: 系统性改进后端测试体系
- 新增 6 个测试场景 (config load pipe, handler errors, service aggregation, engine degradation, openai decoder edges, negative tests) - 更新测试工具规格 (mockgen, in-memory SQLite) - 覆盖率目标从 >80% 提升至 >85% - 新增 test-unit 和 test-integration Makefile 命令 - 新增死代码清理和 mockgen 需求 - 归档变更至 openspec/changes/archive/2026-04-22-improve-backend-testing/
This commit is contained in:
193
backend/tests/config/config_test.go
Normal file
193
backend/tests/config/config_test.go
Normal file
@@ -0,0 +1,193 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"nex/backend/internal/config"
|
||||
)
|
||||
|
||||
func TestLoadConfig_DefaultValues(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
configPath := filepath.Join(tmpDir, "config.yaml")
|
||||
|
||||
cfg, err := config.LoadConfigFromPath(configPath)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, 9826, cfg.Server.Port)
|
||||
assert.Equal(t, 30*time.Second, cfg.Server.ReadTimeout)
|
||||
assert.Equal(t, 30*time.Second, cfg.Server.WriteTimeout)
|
||||
|
||||
assert.Equal(t, 10, cfg.Database.MaxIdleConns)
|
||||
assert.Equal(t, 100, cfg.Database.MaxOpenConns)
|
||||
assert.Equal(t, 1*time.Hour, cfg.Database.ConnMaxLifetime)
|
||||
|
||||
assert.Equal(t, "info", cfg.Log.Level)
|
||||
assert.Equal(t, 100, cfg.Log.MaxSize)
|
||||
assert.Equal(t, 10, cfg.Log.MaxBackups)
|
||||
assert.Equal(t, 30, cfg.Log.MaxAge)
|
||||
assert.True(t, cfg.Log.Compress)
|
||||
}
|
||||
|
||||
func TestLoadConfig_EnvOverride(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
configPath := filepath.Join(tmpDir, "config.yaml")
|
||||
|
||||
t.Setenv("NEX_SERVER_PORT", "9000")
|
||||
t.Setenv("NEX_LOG_LEVEL", "debug")
|
||||
t.Setenv("NEX_DATABASE_MAX_IDLE_CONNS", "20")
|
||||
|
||||
cfg, err := config.LoadConfigFromPath(configPath)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, 9000, cfg.Server.Port)
|
||||
assert.Equal(t, "debug", cfg.Log.Level)
|
||||
assert.Equal(t, 20, cfg.Database.MaxIdleConns)
|
||||
}
|
||||
|
||||
func TestLoadConfig_YAMLFile(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
configPath := filepath.Join(tmpDir, "config.yaml")
|
||||
|
||||
yamlContent := `
|
||||
server:
|
||||
port: 8080
|
||||
read_timeout: 60s
|
||||
write_timeout: 60s
|
||||
database:
|
||||
path: /custom/path.db
|
||||
max_idle_conns: 5
|
||||
max_open_conns: 50
|
||||
conn_max_lifetime: 2h
|
||||
log:
|
||||
level: warn
|
||||
path: /custom/log
|
||||
max_size: 200
|
||||
max_backups: 5
|
||||
max_age: 7
|
||||
compress: false
|
||||
`
|
||||
err := os.WriteFile(configPath, []byte(yamlContent), 0644)
|
||||
require.NoError(t, err)
|
||||
|
||||
cfg, err := config.LoadConfigFromPath(configPath)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, 8080, cfg.Server.Port)
|
||||
assert.Equal(t, 60*time.Second, cfg.Server.ReadTimeout)
|
||||
assert.Equal(t, 60*time.Second, cfg.Server.WriteTimeout)
|
||||
assert.Equal(t, "/custom/path.db", cfg.Database.Path)
|
||||
assert.Equal(t, 5, cfg.Database.MaxIdleConns)
|
||||
assert.Equal(t, 50, cfg.Database.MaxOpenConns)
|
||||
assert.Equal(t, 2*time.Hour, cfg.Database.ConnMaxLifetime)
|
||||
assert.Equal(t, "warn", cfg.Log.Level)
|
||||
assert.Equal(t, "/custom/log", cfg.Log.Path)
|
||||
assert.Equal(t, 200, cfg.Log.MaxSize)
|
||||
assert.Equal(t, 5, cfg.Log.MaxBackups)
|
||||
assert.Equal(t, 7, cfg.Log.MaxAge)
|
||||
assert.False(t, cfg.Log.Compress)
|
||||
}
|
||||
|
||||
func TestLoadConfig_PriorityChain(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
configPath := filepath.Join(tmpDir, "config.yaml")
|
||||
|
||||
yamlContent := `
|
||||
server:
|
||||
port: 8080
|
||||
log:
|
||||
level: warn
|
||||
`
|
||||
err := os.WriteFile(configPath, []byte(yamlContent), 0644)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Setenv("NEX_SERVER_PORT", "9000")
|
||||
|
||||
originalArgs := os.Args
|
||||
defer func() { os.Args = originalArgs }()
|
||||
os.Args = []string{"test", "--server-port", "9999"}
|
||||
|
||||
cfg, err := config.LoadConfigFromPath(configPath)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, 9999, cfg.Server.Port, "CLI should override ENV and YAML")
|
||||
assert.Equal(t, "warn", cfg.Log.Level, "YAML value should be used when no CLI/ENV override")
|
||||
}
|
||||
|
||||
func TestLoadConfig_AutoCreate(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
configPath := filepath.Join(tmpDir, "config.yaml")
|
||||
|
||||
_, err := os.Stat(configPath)
|
||||
assert.True(t, os.IsNotExist(err), "config file should not exist before load")
|
||||
|
||||
cfg, err := config.LoadConfigFromPath(configPath)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, cfg)
|
||||
|
||||
assert.Equal(t, 9826, cfg.Server.Port, "should load with default values")
|
||||
}
|
||||
|
||||
func TestSaveAndLoadConfig(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
|
||||
homeDir, err := os.UserHomeDir()
|
||||
require.NoError(t, err)
|
||||
nexDir := filepath.Join(homeDir, ".nex")
|
||||
configPath := filepath.Join(nexDir, "config.yaml")
|
||||
|
||||
originalConfig, err := os.ReadFile(configPath)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
defer func() {
|
||||
if originalConfig != nil {
|
||||
_ = os.WriteFile(configPath, originalConfig, 0644)
|
||||
}
|
||||
}()
|
||||
|
||||
cfg := &config.Config{
|
||||
Server: config.ServerConfig{
|
||||
Port: 7777,
|
||||
ReadTimeout: 45 * time.Second,
|
||||
WriteTimeout: 45 * time.Second,
|
||||
},
|
||||
Database: config.DatabaseConfig{
|
||||
Path: filepath.Join(tmpDir, "test.db"),
|
||||
MaxIdleConns: 15,
|
||||
MaxOpenConns: 150,
|
||||
ConnMaxLifetime: 2 * time.Hour,
|
||||
},
|
||||
Log: config.LogConfig{
|
||||
Level: "debug",
|
||||
Path: filepath.Join(tmpDir, "log"),
|
||||
MaxSize: 50,
|
||||
MaxBackups: 3,
|
||||
MaxAge: 14,
|
||||
Compress: false,
|
||||
},
|
||||
}
|
||||
|
||||
err = config.SaveConfig(cfg)
|
||||
require.NoError(t, err)
|
||||
|
||||
loaded, err := config.LoadConfig()
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, cfg.Server.Port, loaded.Server.Port)
|
||||
assert.Equal(t, cfg.Server.ReadTimeout, loaded.Server.ReadTimeout)
|
||||
assert.Equal(t, cfg.Server.WriteTimeout, loaded.Server.WriteTimeout)
|
||||
assert.Equal(t, cfg.Database.MaxIdleConns, loaded.Database.MaxIdleConns)
|
||||
assert.Equal(t, cfg.Database.MaxOpenConns, loaded.Database.MaxOpenConns)
|
||||
assert.Equal(t, cfg.Database.ConnMaxLifetime, loaded.Database.ConnMaxLifetime)
|
||||
assert.Equal(t, cfg.Log.Level, loaded.Log.Level)
|
||||
assert.Equal(t, cfg.Log.MaxSize, loaded.Log.MaxSize)
|
||||
assert.Equal(t, cfg.Log.MaxBackups, loaded.Log.MaxBackups)
|
||||
assert.Equal(t, cfg.Log.MaxAge, loaded.Log.MaxAge)
|
||||
assert.Equal(t, cfg.Log.Compress, loaded.Log.Compress)
|
||||
}
|
||||
Reference in New Issue
Block a user