如何用反射测试方法?

时间:2016-07-11 05:39:55

标签: unit-testing go

我有一个方法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
}

1 个答案:

答案 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 } 的测试函数中,创建一个测试配置,使用上面的方法初始化测试环境,并在配置值上调用SyncSync专门针对失败的转化定义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) } } ,因此不应出现任何引起恐慌的原因。