如何在golang中测试打印到控制台的方法?

时间:2017-11-14 08:37:22

标签: unit-testing go

我有下一个结构。

package logger

import "fmt"

type IPrinter interface {
    Print(value string)
}

type ConsolePrinter struct{}

func (cp *ConsolePrinter) Print(value string) {
    fmt.Printf("this is value: %s", value)
}

测试覆盖率说我需要测试ConsolePrinter打印方法。

我该如何报道此方法?

感谢。

3 个答案:

答案 0 :(得分:6)

使用Examples传达函数的用法。

不要担心超过100%的测试覆盖率,特别是对于简单直接的功能。

func ExampleHello() {
    fmt.Println("hello")
    // Output: hello
}

额外的好处是使用go doc工具在生成的文档中输出examples

答案 1 :(得分:1)

我建议创建logger的新实例,其行为与用于将数据打印到控制台的fmt方法完全相同。此外,您可以使用其他功能(如显示文件名,日期等)对其进行配置。此类自定义记录器可作为参数传递给您的服务/实例工厂方法。这将使模拟和测试变得非常容易。

您的代码

type Logs interface {
    Println(v ...interface{})
}

type InstanceToTest struct {
    log Logs
}

func InstanceToTestFactory(logger Logs) *InstanceToTest {
    return &InstanceToTest{logger}
}

func (i *InstanceToTest) SomeMethod(a string) {
    i.log.Println(a)
}

为记录器创建模拟

type LoggerMock struct {
    CalledPrintln []interface{}    
}

func (l *LoggerMock) Println(v ...interface{}) {
    l.CalledPrintln = append(CalledPrintln, v)
}

在你的考试中

func TestInstanceToTestSomeMethod(t *testing.T) {
    l := &LoggerMock{}
    i := InstanceToTestFactory(l)
    a := "Test"

    i.SomeMethod(a)

    if len(l.CalledPrintln) == 0 || l.CalledPrintln[0] != a {
        t.Error("Not called")
    }
}

答案 2 :(得分:0)

在@icza写的评论之后,我已经在下面写了测试。

func TestPrint(t *testing.T) {
    rescueStdout := os.Stdout
    r, w, _ := os.Pipe()
    os.Stdout = w

    cp := &ConsolePrinter{}
    cp.Print("test")

    w.Close()
    out, _ := ioutil.ReadAll(r)
    os.Stdout = rescueStdout

    if string(out) != "this is value: test" {
        t.Errorf("Expected %s, got %s", "this is value: test", out)
    }
}

我找到了问题What is the best way to convert byte array to string?中的例子。