问题记录:flag provided but not defined: -test.v 异常处理过程

问题描述

工作需求,写了一个底层调用的方法,就想测一测这个接口别有什么问题,于是写了一个单元测试用例,试着跑了一下,就报了下面这个错误
flag provided but not defined: -test.v
单元测试代码:

func TestA(t *testing.T) {
    type args struct {
        ctx    context.Context
        key    string
        secret string
        msg    string
    }
    tests := []struct {
        name    string
        args    args
        want    []byte
        wantErr bool
    }{
        {
            name: "正常",
            args: args{
                ctx:    context.Background(),
                key:    "key_test",
                secret: "secret_test",
                msg:    "你好呀,小朋友",
            },
        },
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            got, err := baseService.A(tt.args.ctx, tt.args.key, tt.args.secret, tt.args.msg)
            if (err != nil) != tt.wantErr {
                t.Errorf("A() error = %v, wantErr %v", err, tt.wantErr)
                return
            }
            if !reflect.DeepEqual(got, tt.want) {
                t.Errorf("A() got = %v, want %v", got, tt.want)
            }
        })
    }
}

问题原因追溯

1. -test.v是testing包中定义的命令行参数,flag provided but not defined 是flag包的Parse()方法调用时抛的异常。
2. 测试代码中有引用自定义的参数命令行参数,再底层引用中找到了下面这段代码
var usr1 = flag.String("usr1", "", "user defined flag -usr1")
var usr2 = flag.String("usr2", "", "user defined flag -usr2")
var usr3 = flag.String("usr3", "", "user defined flag -usr3")
var usr4 = flag.String("usr4", "", "user defined flag -usr4")
var usr5 = flag.String("usr5", "", "user defined flag -usr5")

func init() {
    if !flag.Parsed() {
        flag.Parse()
    }
}

init方法中定义的flag再运行中都有提示给出,猜测是init方法中调用的Parse方法调用时,testing中的命令行参数还没有被解析

3. 再看下Parse()方法的实现代码
    s := f.args[0]  //取执行时的命令行参数
    name := s[numMinuses:] 命令行参数名称处理
    m := f.formal 已初始化的命令行参数
    flag, alreadythere := m[name] 
    if !alreadythere { //执行时带的命令行参数如果没有被初始化就报错
        if name == "help" || name == "h" { // special case for nice help message.
            f.usage()
            return false, ErrHelp
        }
        return false, f.failf("flag provided but not defined: -%s", name)
    }
4. 上面跑出的异常就是由3处的函数调用产生的,我们再确认下testing的命令行参数初始化代码
func Init() {
    chatty = flag.Bool("test.v", false, "verbose: print     additional output")
    count = flag.Uint("test.count", 1, "run tests and   benchmarks `n` times")
}
func MainStart(deps testDeps, tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) *M {
    Init()
    return &M{
        deps:       deps,
        tests:      tests,
        benchmarks: benchmarks,
        examples:   examples,
    }
}
func Main(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) {
    os.Exit(MainStart(matchStringOnly(matchString), tests, benchmarks, examples).Run())
}   

testing的命令行初始化实在运行时才开始的。所以可以确认是自定义包中的初始化函数中的flag.Parse()引起的。

问题解决

定位了问题之后,我们在测试用例中再手动引入testing.Init()方法,使其在引用了flag.Parse()包之前被初始化掉。

import (
    "context"
    "reflect"
    "testing"

    _ "app/test/init"

    "app/service/baseService"
)
//app/test/init/init.go
import "testing"

func init(){
    testing.Init()
}

再次运行测试用例,不再报错


image.png

你可能感兴趣的:(问题记录:flag provided but not defined: -test.v 异常处理过程)