gpt4 book ai didi

unit-testing - 如何用reflect测试方法?

转载 作者:数据小太阳 更新时间:2023-10-29 03:15:04 25 4
gpt4 key购买 nike

我有一个 Sync() 方法可以覆盖在环境中设置的 Config 字段值。环境变量名称是通过下划线和大写名称从配置字段派生的。例如。 AppName会有一个对应的环境变量APP_NAME

请帮我测试以下情况。有复杂的东西,比如 https://golang.org/pkg/reflect/#Value.Set :

Set assigns x to the value v. It panics if CanSet returns false. As in Go, x's value must be assignable to v's type.

所以我不知道如何测试这个案例?

import (
"encoding/json"
"errors"
"fmt"
"os"
"path/filepath"
"reflect"
"strconv"
"strings"
"github.com/BurntSushi/toml"
"github.com/fatih/camelcase"
"gopkg.in/yaml.v2"
)

type Config struct {
AppName string
BaseURL string
Port int
Verbose bool
StaticDir string
ViewsDir string
}

func (c *Config) Sync() error {
cfg := reflect.ValueOf(c).Elem()
cTyp := cfg.Type()

for k := range make([]struct{}, cTyp.NumField()) {
field := cTyp.Field(k)

cm := getEnvName(field.Name)
env := os.Getenv(cm)
if env == "" {
continue
}
switch field.Type.Kind() {
case reflect.String:
cfg.FieldByName(field.Name).SetString(env)
case reflect.Int:
v, err := strconv.Atoi(env)
if err != nil {
return fmt.Errorf("loading config field %s %v", field.Name, err)
}
cfg.FieldByName(field.Name).Set(reflect.ValueOf(v))
case reflect.Bool:
b, err := strconv.ParseBool(env)
if err != nil {
return fmt.Errorf("loading config field %s %v", field.Name, err)
}
cfg.FieldByName(field.Name).SetBool(b)
}

}
return nil
}

最佳答案

如果您想在调用 Sync 后测试对 Cofig 所做的更改,请在您的测试中定义一个设置环境的函数:

func SetTestEnv(key, value string) error; err != nil {
if err := os.Setenv(key, value string) {
return err
}
return nil
}

现在,您可以测试 Sync 函数,创建测试配置,使用上述方法初始化测试环境,并在配置值上调用 Syncstrconv 专门针对失败的转换定义了 NumError。你可以利用它:

func TestSync(t *testing.T) {
c : Config{
// initialize config, or do it through another method
// e.g. func InitConfig(...) *Config {..}
}

// set the environment
SetTestEnv("APP_NAME", "app name")
SetTestEnv("BASE_URL", "base url")
SetTestEnv("PORT", "port number") // will cause error
// etc..

if err := c.Sync(); err != nil {
e, ok := err.(*strconv.NumError)
if !ok {
t.Errorf("Unexpected error")
} else if e.Err != strconv.ErrSyntax { // check specifically for expected syntax error
t.Errorf("Expected conversion to fail")
}

}

SetTestEnv("PORT", "1000") // correct port number

if err := c.Sync(); err != nil {
t.Errorf("Unexpected error in Sync: %v", err)
}
}

由于您确保使用类型开关以正确的值类型调用 Set,因此不应有任何原因导致 panic 发生。

关于unit-testing - 如何用reflect测试方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38299819/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com