我有以下Golang代码:
func getConfigFile() string {
var configFile string
flag.StringVar(&configFile, "config", "", "File containing configuration")
flag.Parse()
return configFile
}
这个函数在我的代码的其他地方使用,我想在用户为config参数提供不同的值时对这里发生的事情进行单元测试(配置文件名在其他地方使用)。
有没有办法告诉标志包在测试时为config参数返回不同的值?
答案 0 :(得分:1)
我发现,为了测试自定义标志最好创建一个自定义标志集,这样我就可以完全测试标志,包括-h
选项而不退出测试。希望附加的代码可以为您提供有关如何在代码上实现测试的想法:
package main
import (
"flag"
"fmt"
"os"
"reflect"
"testing"
)
// Test Helper
func expect(t *testing.T, a interface{}, b interface{}) {
if a != b {
t.Errorf("Expected: %v (type %v) Got: %v (type %v)", a, reflect.TypeOf(a), b, reflect.TypeOf(b))
}
}
type Flags struct {
ConfigFile string
}
func (self *Flags) Parse(fs *flag.FlagSet) (*Flags, error) {
fs.StringVar(&self.ConfigFile, "config", "", "File containing configuration")
err := fs.Parse(os.Args[1:])
if err != nil {
return nil, err
}
return self, nil
}
func main() {
fs := flag.NewFlagSet("test", flag.ContinueOnError)
parser := Flags{}
flags, err := parser.Parse(fs)
if err != nil {
panic(err)
}
fmt.Println(flags)
}
func TestFlags(t *testing.T) {
oldArgs := os.Args
defer func() { os.Args = oldArgs }()
var flagTest = []struct {
flag []string
name string
expected interface{}
}{
{[]string{"cmd", "-config", "config.yaml"}, "ConfigFile", "config.yaml"},
{[]string{"cmd", "-config", "config.json"}, "ConfigFile", "config.json"},
{[]string{"cmd", "-v"}, "Version", true},
}
for _, f := range flagTest {
os.Args = f.flag
p := &Flags{}
fs := flag.NewFlagSet("test", flag.ContinueOnError)
flags, err := p.Parse(fs)
if err != nil {
t.Error(err)
}
refValue := reflect.ValueOf(flags).Elem().FieldByName(f.name)
switch refValue.Kind() {
case reflect.Bool:
expect(t, f.expected, refValue.Bool())
case reflect.String:
expect(t, f.expected, refValue.String())
}
}
}
我也把它放在这里:https://play.golang.org/p/h1nok1UMLA希望它可以给你一个想法。
答案 1 :(得分:0)
如果您按照以下代码进行更改,则go test
将失败,但go test -config testconfig
将通过。并非我们不需要在flag.Parse()
中调用init()
,因为测试包会调用它(正如Rob Pike在https://groups.google.com/d/msg/golang-nuts/uSFM8jG7yn4/PIQfEWOZx4EJ中提到的那样)。
package main
import (
"flag"
"testing"
)
var configFile = flag.String("config", "", "File containing configuration")
func getConfigFile() string {
return *configFile
}
func TestConfig(t *testing.T) {
want := "testconfig"
if s := getConfigFile(); s != want {
t.Errorf("Got %s, want %s", s, want)
}
}
测试运行:
$ go test
--- FAIL: TestConfig (0.00s)
flag_test.go:17: Got , want testconfig
FAIL
exit status 1
FAIL github.com/dmitris/soflagtest 0.013s
$ go test -config testconfig
PASS
ok github.com/dmitris/soflagtest 0.012s
您也可以使用
var configFile string
声明和init()
函数将标志值赋给变量:
func init() {
flag.StringVar(&configFile, "config", "", "File containing configuration")
}
(然后在getConfigFile中没有指针解除引用,因为configFile是一个字符串)