我有一个方法Sync(),它覆盖了在环境中设置的Config
字段值。
环境变量名称通过下划线从配置字段派生,并在名称上加上大写。例如。 AppName将具有相应的环境变量APP_NAME
请帮我测试下列情况。有一些复杂的事情,如https://golang.org/pkg/reflect/#Value.Set:
Set将x赋值给v。如果CanSet返回false,则会发生恐慌。如在 Go,x的值必须分配给v的类型。
所以我不知道如何测试这个案子?
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
}
答案 0 :(得分:1)
如果要在调用BOOL isContainsDict = NO;
for (id value in Array){
if ([value isKindOfClass:[NSDictionary class]]){
isContainsDict = YES;
break; // end since you only want to know if the array contains an instance of dictionary. if it does no need to continue the loop just break and perform the process
}
}
后测试对Cofig
所做的更改,请在测试中定义一个设置环境的函数:
Sync
现在在func SetTestEnv(key, value string) error; err != nil {
if err := os.Setenv(key, value string) {
return err
}
return nil
}
的测试函数中,创建一个测试配置,使用上面的方法初始化测试环境,并在配置值上调用Sync
。 Sync
专门针对失败的转化定义strconv
。你可以利用它:
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)
}
}
,因此不应出现任何引起恐慌的原因。