在Golang项目里,配置文件加载模块的正确性直接影响整个程序的运行稳定性,我们需要通过单元测试覆盖配置加载、默认值赋值、异常处理等核心场景,确保逻辑无漏洞。

配置加载模块的基础实现
首先我们先实现一个简单的配置文件加载模块,支持从YAML文件读取配置,同时支持设置默认值,以及处理加载过程中的异常。以下是配置结构体和加载函数的实现:
package config
import (
"fmt"
"os"
"path/filepath"
"gopkg.in/yaml.v3"
)
// AppConfig 应用配置结构体
type AppConfig struct {
ServerPort int `yaml:"server_port"`
DBHost string `yaml:"db_host"`
DBPort int `yaml:"db_port"`
LogLevel string `yaml:"log_level"`
}
// defaultConfig 返回默认配置
func defaultConfig() *AppConfig {
return &AppConfig{
ServerPort: 8080,
DBHost: "127.0.0.1",
DBPort: 3306,
LogLevel: "info",
}
}
// LoadConfig 加载配置文件,path为配置文件路径
func LoadConfig(path string) (*AppConfig, error) {
cfg := defaultConfig()
// 如果传入路径为空,直接返回默认配置
if path == "" {
return cfg, nil
}
// 获取绝对路径,避免相对路径问题
absPath, err := filepath.Abs(path)
if err != nil {
return nil, fmt.Errorf("获取配置文件绝对路径失败: %w", err)
}
// 读取文件内容
data, err := os.ReadFile(absPath)
if err != nil {
return nil, fmt.Errorf("读取配置文件失败: %w", err)
}
// 解析YAML内容
err = yaml.Unmarshal(data, cfg)
if err != nil {
return nil, fmt.Errorf("解析配置文件失败: %w", err)
}
return cfg, nil
}
测试核心场景分析
针对配置加载模块,我们需要覆盖以下测试场景:
- 不传入配置文件路径时,是否正确返回默认值
- 传入正确的配置文件时,是否正确覆盖默认值
- 配置文件路径不存在时,是否返回对应的错误
- 配置文件格式错误时,是否返回解析错误
- 配置文件部分字段缺失时,是否保留默认值
完整测试代码实现
我们使用Golang自带的testing包编写测试用例,同时使用testify/assert包简化断言逻辑,测试代码如下:
package config_test
import (
"path/filepath"
"testing"
"your_project/config"
"github.com/stretchr/testify/assert"
)
// TestLoadConfig_WithEmptyPath 测试不传入路径时返回默认配置
func TestLoadConfig_WithEmptyPath(t *testing.T) {
cfg, err := config.LoadConfig("")
assert.NoError(t, err)
assert.Equal(t, 8080, cfg.ServerPort)
assert.Equal(t, "127.0.0.1", cfg.DBHost)
assert.Equal(t, 3306, cfg.DBPort)
assert.Equal(t, "info", cfg.LogLevel)
}
// TestLoadConfig_WithValidConfig 测试传入正确配置文件时覆盖默认值
func TestLoadConfig_WithValidConfig(t *testing.T) {
// 准备临时配置文件
testConfig := `
server_port: 9090
db_host: 192.168.0.1
db_port: 5432
log_level: debug
`
tmpFile := filepath.Join(t.TempDir(), "config.yaml")
err := os.WriteFile(tmpFile, []byte(testConfig), 0644)
assert.NoError(t, err)
cfg, err := config.LoadConfig(tmpFile)
assert.NoError(t, err)
assert.Equal(t, 9090, cfg.ServerPort)
assert.Equal(t, "192.168.0.1", cfg.DBHost)
assert.Equal(t, 5432, cfg.DBPort)
assert.Equal(t, "debug", cfg.LogLevel)
}
// TestLoadConfig_FileNotExist 测试配置文件不存在的场景
func TestLoadConfig_FileNotExist(t *testing.T) {
_, err := config.LoadConfig("not_exist_config.yaml")
assert.Error(t, err)
assert.Contains(t, err.Error(), "读取配置文件失败")
}
// TestLoadConfig_InvalidYaml 测试配置文件格式错误的场景
func TestLoadConfig_InvalidYaml(t *testing.T) {
invalidConfig := `
server_port: 9090
db_host: 192.168.0.1
db_port: 5432 # 错误缩进导致YAML格式无效
`
tmpFile := filepath.Join(t.TempDir(), "invalid_config.yaml")
err := os.WriteFile(tmpFile, []byte(invalidConfig), 0644)
assert.NoError(t, err)
_, err = config.LoadConfig(tmpFile)
assert.Error(t, err)
assert.Contains(t, err.Error(), "解析配置文件失败")
}
// TestLoadConfig_PartialConfig 测试配置文件部分字段缺失时保留默认值
func TestLoadConfig_PartialConfig(t *testing.T) {
partialConfig := `
server_port: 7070
# 其他字段未配置,应使用默认值
`
tmpFile := filepath.Join(t.TempDir(), "partial_config.yaml")
err := os.WriteFile(tmpFile, []byte(partialConfig), 0644)
assert.NoError(t, err)
cfg, err := config.LoadConfig(tmpFile)
assert.NoError(t, err)
assert.Equal(t, 7070, cfg.ServerPort)
// 以下字段未配置,应保留默认值
assert.Equal(t, "127.0.0.1", cfg.DBHost)
assert.Equal(t, 3306, cfg.DBPort)
assert.Equal(t, "info", cfg.LogLevel)
}
测试执行与结果验证
在包含测试文件的目录下执行go test -v命令,即可运行所有测试用例,输出结果会显示每个用例的执行状态。如果所有用例都通过,说明配置加载模块的默认值逻辑和异常处理逻辑都符合预期。如果用例失败,可以根据错误提示定位对应场景的问题,调整配置加载的实现代码。
注意事项
- 测试时尽量使用临时目录存放测试用的配置文件,避免污染项目实际文件,测试结束后临时目录会自动清理
- 异常测试需要验证错误内容是否符合预期,不能仅判断返回了错误就通过,要确保是错误的类型
- 如果配置加载依赖第三方包,测试时可以通过接口抽象配置加载逻辑,方便后续做 mock 测试