无法测试Golang CLI工具的输出

时间:2015-12-04 19:11:59

标签: go command-line-interface

我有一个用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

1 个答案:

答案 0 :(得分:0)

好的,所以这个问题的解决方案是部分架构和部件删除/重构代码。

  1. 我从cli命令包中提取了私有函数,因此它们在单独的函数中成为公共函数

  2. 我重构了代码,以便注入所有依赖项,然后允许我模拟这些对象并验证预期的方法被调用

  3. 现在私有函数在一个包中并公开,我能够在cli上下文之外专门测试这些东西

  4. 最后,我删除了os.Exit的使用,因为这是一个噩梦来处理,并不是真的有必要