我有一个用Go编写的cli工具,它产生以下输出:
Command: config get
Env: int
Component: foo-component
Unable to find any configuration within Cosmos (http://api.foo.com) for foo-component.
我想在测试中验证此输出。
我写的(并且未通过)测试如下:
package command
import (
"testing"
"github.com/my/package/foo"
)
type FakeCliContext struct{}
func (s FakeCliContext) String(name string) string {
return "foobar"
}
func ExampleInvalidComponentReturnsError() {
fakeBaseURL := "http://api.foo.com"
fakeCliContext := &FakeCliContext{}
fakeFetchFlag := func(foo.CliContext) (map[string]string, error) {
return map[string]string{
"env": "int",
"component": "foo-component",
}, nil
}
GetConfig(*fakeCliContext, fakeFetchFlag, fakeBaseURL)
// Output:
// Command: config get
// Env: int
// Component: foo-component
//
// Unable to find any configuration within Cosmos (http://api.foo.com) for foo-component.
}
大部分代码都是在我的函数调用GetConfig
中创建虚假对象。
实际上,GetConfig
没有返回值,只会将文本的副作用打印到标准输出。
所以我使用Example<NameOfTest>
格式来尝试验证输出。
但是,当我运行go test -v
时,我刚刚回来的是:
=== RUN ExampleInvalidComponentReturnsError
exit status 1
FAIL github.com/my/package/thing 0.418s
有谁知道我可能会缺少什么?
我发现如果我在上面的'Example'之后添加一个额外的测试,例如调用Test<NameOfTest>
(但实际上是有效的相同代码),那么这实际上会显示函数的输出到我的运行测试时的stdout:
func TestInvalidComponentReturnsError(t *testing.T) {
fakeBaseURL := "http://api.foo.com"
fakeCliContext := &FakeCliContext{}
fakeFetchFlag := func(utils.CliContext) (map[string]string, error) {
return map[string]string{
"env": "int",
"component": "foo-component",
}, nil
}
GetConfig(*fakeCliContext, fakeFetchFlag, fakeBaseURL)
}
上面的示例测试现在将在执行go test -v
时显示以下输出:
=== RUN TestInvalidComponentReturnsError
Command: config get
Env: int
Component: foo-component
Unable to find any configuration within Cosmos (http://api.foo.com) for foo-component.
exit status 1
FAIL github.com/bbc/apollo/command 0.938s
答案 0 :(得分:0)
好的,所以这个问题的解决方案是部分架构和部件删除/重构代码。
我从cli命令包中提取了私有函数,因此它们在单独的函数中成为公共函数
我重构了代码,以便注入所有依赖项,然后允许我模拟这些对象并验证预期的方法被调用
现在私有函数在一个包中并公开,我能够在cli上下文之外专门测试这些东西
最后,我删除了os.Exit的使用,因为这是一个噩梦来处理,并不是真的有必要