如何模拟 *exec.Cmd / exec.Command()?

我需要嘲笑exec.Command()。


我可以使用以下方法模拟它:


var rName string

var rArgs []string


mockExecCommand := func(name string, arg ...string) *exec.Cmd {

    rName = name

    rArgs = arg


    return nil

}

但是,这在实际代码中不起作用,因为它抱怨 nil 指针,因为返回exec.Cmd调用Run().


我试图像这样模拟它:


type mock exec.Cmd


func (m *mock) Run() error {

    return nil

}


var rName string

var rArgs []string


mockExecCommand := func(name string, arg ...string) *exec.Cmd {

    rName = name

    rArgs = arg


    m := mock{}


    return &m

}

但它抱怨:cannot use &m (value of type *mock) as *exec.Cmd value in return statementcompilerIncompatibleAssign.


有没有办法解决这个问题?有没有更好的模拟方法exec.Command()?


如果我返回一个“模拟”命令,模拟函数就可以工作,尽管我Run()也更喜欢控制这个函数:


var rName string

var rArgs []string


mockExecCommand := func(name string, arg ...string) *exec.Cmd {

    rName = name

    rArgs = arg


    return exec.Command("echo")

}


Qyouu
浏览 119回答 3
3回答

肥皂起泡泡

虽然劫持测试可执行文件以运行特定功能是可行的,但仅使用常规依赖注入会更直接。不需要魔法。设计一个可以运行命令的界面(例如CommandExecutor),然后将其中一个作为您的输入,用于运行命令所需的任何功能。然后,您可以在测试期间提供满足接口(手工制作或使用您选择的工具生成,如 GoMock)的模拟实现。为您的生产代码提供真正的实现(调用exec包)。您的模拟实现甚至可以对参数进行断言,以便您知道命令正在正确“执行”。

慕标琳琳

实际上有一种方法可以做到这一点。所有功劳归于这篇文章。查看它以了解以下发生的情况:func fakeExecCommand(command string, args...string) *exec.Cmd {    cs := []string{"-test.run=TestHelperProcess", "--", command}    cs = append(cs, args...)    cmd := exec.Command(os.Args[0], cs...)    cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}    return cmd}func TestHelperProcess(t *testing.T){    if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {        return    }    os.Exit(0)}

繁星淼淼

如何模拟 *exec.Cmd / exec.Command()?你不能。提出一个非基于模拟的测试策略。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go