为bufio.NewScanner模拟stdout流

时间:2016-07-25 09:03:08

标签: testing go io mocking stdout

我想为使用bufio.NewScannerScan()的效用函数编写测试。我通常在stdout上使用它,现在我想模拟一小段流,我可以返回一些静态字符串用于测试。

bufio.NewScanner(r io.Reader)需要Reader,但只需要read方法。通过阅读源代码,我无法弄清楚它从哪个缓冲区读取或传入的方式。

我怎样才能以简洁明了的方式嘲笑它?

2 个答案:

答案 0 :(得分:4)

要简单测试您的代码,您可以使用@Sven的答案。

要了解一个简单的io.Reader进行测试,请考虑以下示例:

type R struct {
    Data string
    done bool
}

func (r *R) Read(p []byte) (n int, err error) {
    copy(p, []byte(r.Data))
    if r.done {
        return 0, io.EOF
    }
    r.done = true
    return len([]byte(r.Data)), nil
}

R是一种自定义测试类型,它通过io.Reader方法实现Read接口。因此,它将被NewScanner接受。它可以用作:

func NewR(data string) *R {
    return &R{data, false}
}

r := NewR("Test\nmessage\n")
scanner := bufio.NewScanner(r)

for scanner.Scan() {
    fmt.Printf("Line: %s\n", scanner.Text())
}

输出:

Line: Test 
Line: message

类型R及其Read方法都已定义为简单的字节源。 Scan会调用其读者(输入NewScannerRead方法,直到获得EOF或错误为止。为简单起见,R Read方法在其第一次调用中将其数据复制到调用者的缓冲区(p),并为任何一个返回EOF后续电话。

请注意,\n处的行的实际拆分由scanner.Scan而不是r.Read完成。

您可以修改上面的Read方法,以根据您的要求获得自定义行为。

工作示例:https://play.golang.org/p/zqDoQDIE93

答案 1 :(得分:2)

您可以使用bytes.Buffer,因为它实现了io.Reader函数。

示例 https://play.golang.org/p/gjjMmT3SzD

package main

import (
    "bufio"
    "bytes"
    "fmt"
)

func main() {
    buf := bytes.NewBufferString("foo\nbar")
    scanner := bufio.NewScanner(buf)
    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }
}