为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
Qyouu 2022-11-08 15:43:17
我需要嘲笑exec.Command()。我可以使用以下方法模拟它:var rName stringvar rArgs []stringmockExecCommand := func(name string, arg ...string) *exec.Cmd {    rName = name    rArgs = arg    return nil}但是,这在实际代码中不起作用,因为它抱怨 nil 指针,因为返回exec.Cmd调用Run().我试图像这样模拟它:type mock exec.Cmdfunc (m *mock) Run() error {    return nil}var rName stringvar rArgs []stringmockExecCommand := 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 stringvar rArgs []stringmockExecCommand := func(name string, arg ...string) *exec.Cmd {    rName = name    rArgs = arg    return exec.Command("echo")}
查看完整描述

3 回答

?
肥皂起泡泡

TA贡献1829条经验 获得超6个赞

虽然劫持测试可执行文件以运行特定功能是可行的,但仅使用常规依赖注入会更直接。不需要魔法。

设计一个可以运行命令的界面(例如CommandExecutor),然后将其中一个作为您的输入,用于运行命令所需的任何功能。然后,您可以在测试期间提供满足接口(手工制作或使用您选择的工具生成,如 GoMock)的模拟实现。为您的生产代码提供真正的实现(调用exec包)。您的模拟实现甚至可以对参数进行断言,以便您知道命令正在正确“执行”。


查看完整回答
反对 回复 2022-11-08
?
慕标琳琳

TA贡献1830条经验 获得超9个赞

实际上有一种方法可以做到这一点。所有功劳归于这篇文章。查看它以了解以下发生的情况:


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)

}


查看完整回答
反对 回复 2022-11-08
?
繁星淼淼

TA贡献1775条经验 获得超11个赞

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

你不能。提出一个非基于模拟的测试策略。


查看完整回答
反对 回复 2022-11-08
  • 3 回答
  • 0 关注
  • 118 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信