我需要嘲笑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()
?
如果我返回一个“mock”命令,mock函数就可以工作,尽管我更喜欢控制Run()
函数:
var rName string
var rArgs []string
mockExecCommand := func(name string, arg ...string) *exec.Cmd {
rName = name
rArgs = arg
return exec.Command("echo")
}
4条答案
按热度按时间scyqe7ek1#
实际上有一种方法可以做到这一点。所有的功劳都归功于this文章。请查看它以了解下面所发生的事情的解释:
9lowa7mx2#
虽然劫持测试可执行文件来运行一个特定的函数是可行的,但使用常规的依赖注入会更直接。
设计界面(例如
CommandExecutor
),然后将其中一个作为运行命令所需函数的输入。(手工制作或使用您选择的工具生成,比如GoMock)。提供真实的的实现(它调用exec
包)。您的模拟实现甚至可以对参数进行Assert,这样您就知道命令正在正确地“执行”。x7yiwoj43#
我所知道的在go中最好的方法是使用多态性。你的思路是对的。详细的解释在https://github.com/schollii/go-test-mock-exec-command,我创建它是因为当我搜索如何模仿
os/exec
时,我所能找到的只是在另一个答案中提到的env变量技术。这种方法是绝对没有必要的,正如我在链接到的git repo的自述文件中提到的,它所需要的只是一点多态性。总结基本上是这样的:
1.为
exec.Cmd
创建一个接口类,它只包含应用程序(或模块)代码使用的必要方法1.创建一个实现该接口的结构,例如它可以只提到
exec.Cmd
1.创建一个包级var(已导出),它指向一个返回步骤2中的结构的函数
1.使应用程序代码使用该包级变量
1.使测试创建一个实现该接口的新结构,但只包含输出和退出代码,并使测试用该新结构的示例替换该包级var
它在应用程序代码中看起来如下所示:
在测试端,它看起来像这样:
xytpbqjk4#
如何模拟 * exec.cmd/exec.command()?
你不能。想出一个非基于模拟的测试策略。