Golang Viper库 - 如何模拟测试配置

Golang Viper库 - 如何模拟测试配置 你好,

我是 Golang 编程的初学者,在测试我的服务时遇到了问题。

我的 yml 文件中有一个如下所示的配置文件:

service:
max:
limit: 5
error: false

我正在使用 Viper 来读取配置,例如:

maxerror =config.Viper.GetString("service.max.error")

假设我的代码中有一个条件:

if strings.EqualFold(maxerror, "true") {
//执行某些操作
} else{
//执行其他操作
}

我的 “service.max.error” 配置设置为 “true”。因此在测试时,只有 “if 块” 会执行。我应该如何模拟/覆盖该属性值来测试 “else” 块。


更多关于Golang Viper库 - 如何模拟测试配置的实战教程也可以访问 https://www.itying.com/category-94-b0.html

4 回复

能否请您将代码放入代码块中,使其更易读?

更多关于Golang Viper库 - 如何模拟测试配置的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


@kync,感谢您的意见。我已经更新了代码部分。能否请您重新检查一下帖子?

将你的函数/方法改为从外部接收参数,并将 maxError 作为参数传递给该函数。尽量避免将依赖项注入到函数中。

读取 viper,获取最大错误

//maxError := config.Viper.GetString("service.max.error")
func doSomething(maxError string) (ret interface{}){
   if strings.EqualFold(maxerror, "true") {
   //执行某些操作
   } else{
   //执行其他操作
   }
}

func TestDoSomething(t *testing.T){
   retVal := doSomething(5)
   if retVal  != 5{
       t.Errorf("doSomething(5) = %d; 期望得到 5", retVal)
   }
}

你可以通过多种方式在测试中模拟 Viper 的配置值。以下是几种实用的方法:

方法1:使用 Viper 的 Set 方法

func TestElseBlock(t *testing.T) {
    // 保存原始值
    originalValue := viper.GetString("service.max.error")
    defer viper.Set("service.max.error", originalValue) // 测试后恢复
    
    // 设置测试值
    viper.Set("service.max.error", "false")
    
    maxerror := viper.GetString("service.max.error")
    
    if strings.EqualFold(maxerror, "true") {
        t.Error("Expected false, but condition entered true block")
    } else {
        // 这里会执行 else 块,可以添加你的测试断言
        t.Log("Successfully tested else block")
    }
}

方法2:使用 Viper 实例隔离测试

func TestWithIsolatedViper(t *testing.T) {
    testViper := viper.New()
    testViper.Set("service.max.error", "false")
    
    maxerror := testViper.GetString("service.max.error")
    
    if strings.EqualFold(maxerror, "true") {
        t.Error("Should not enter true block")
    } else {
        // 测试 else 逻辑
        fmt.Println("Testing else block with value:", maxerror)
    }
}

方法3:重构代码以支持依赖注入

type Config interface {
    GetString(key string) string
}

type ViperConfig struct{}

func (v *ViperConfig) GetString(key string) string {
    return viper.GetString(key)
}

func YourFunction(cfg Config) {
    maxerror := cfg.GetString("service.max.error")
    
    if strings.EqualFold(maxerror, "true") {
        // 执行某些操作
    } else {
        // 执行其他操作
    }
}

// 测试代码
type MockConfig struct {
    values map[string]string
}

func (m *MockConfig) GetString(key string) string {
    return m.values[key]
}

func TestYourFunction(t *testing.T) {
    mockConfig := &MockConfig{
        values: map[string]string{
            "service.max.error": "false",
        },
    }
    
    YourFunction(mockConfig) // 这会执行 else 块
}

方法4:使用环境变量覆盖

func TestWithEnvOverride(t *testing.T) {
    t.Setenv("SERVICE_MAX_ERROR", "false")
    
    // 如果你的 Viper 配置了环境变量
    viper.AutomaticEnv()
    viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
    
    maxerror := viper.GetString("service.max.error")
    
    if strings.EqualFold(maxerror, "true") {
        t.Error("Expected false from environment variable")
    } else {
        // 测试 else 块
        fmt.Println("Testing with env value:", maxerror)
    }
}

推荐使用方法1或方法2,它们简单直接,不需要大幅修改现有代码。方法3虽然需要重构,但提供了更好的测试隔离和可维护性。

回到顶部