单元测试不同的标志值

I have the following Golang code:

func getConfigFile() string {
    var configFile string
    flag.StringVar(&configFile, "config", "", "File containing configuration")
    flag.Parse()
    return configFile
}

This function is used elsewhere in my code, and I'd like to unit test what happens here when the user provides different values for the config argument (the config file name is used else where).
Is there a way to tell the flag package to return different values for the config argument while under test?

If you change it like the code below, go test will fail but go test -config testconfig will pass. Not that we don't need to call flag.Parse() in the init() since it is be called by the testing package (as Rob Pike mentions in 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)
    }
}

Test runs:

$ 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

You can also use var configFile string declaration and an init() function to assign the flag value to the variable:

func init() {
     flag.StringVar(&configFile, "config", "", "File containing configuration")
}

(then no pointer dereferencing in getConfigFile since configFile is a string)

I have found that for testing custom flags is better to create a custom flag set, in that way I can fully test the flags, including the -h option without exiting the tests. hope the attached code could give you and idea of how you could implement test on your code:

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())
        }
    }

}

I put it also here: https://play.golang.org/p/h1nok1UMLA hope it can give you an idea.