当前位置: 首页 > 面试题库 >

填充os.Stdin以读取其中的函数

丌官子安
2023-03-14
问题内容

如何在我的测试中填写os.Stdin中使用扫描仪从中读取的功能?

我要求使用以下功能通过扫描仪输入用户命令行:

func userInput() error {
    scanner := bufio.NewScanner(os.Stdin)

    println("What is your name?")
    scanner.Scan()
    username = scanner.Text()

    /* ... */
}

现在如何测试这种情况并模拟用户输入?以下示例不起作用。Stdin还是空的。

func TestUserInput(t *testing.T) {
    var file *os.File
    file.Write([]byte("Tom"))
    os.Stdin = file

    err := userInput()
    /* ... */
}

问题答案:

嘲笑 os.Stdin

您在正确的位置上,os.Stdin该变量是*os.File您可以修改的(类型为),可以在测试中为其分配新值。

最简单的方法是使用您要模拟的内容作为输入创建一个临时文件os.Stdin。要创建临时文件,请使用ioutil.TempFile()。然后将内容写入其中,并返回到文件的开头。现在,您可以将其设置为os.Stdin并执行测试。不要忘记清理临时文件。

我将您修改userInput()为:

func userInput() error {
    scanner := bufio.NewScanner(os.Stdin)

    fmt.Println("What is your name?")
    var username string
    if scanner.Scan() {
        username = scanner.Text()
    }
    if err := scanner.Err(); err != nil {
        return err
    }

    fmt.Println("Entered:", username)
    return nil
}

这就是您可以测试的方式:

func TestUserInput(t *testing.T) {
    content := []byte("Tom")
    tmpfile, err := ioutil.TempFile("", "example")
    if err != nil {
        log.Fatal(err)
    }

    defer os.Remove(tmpfile.Name()) // clean up

    if _, err := tmpfile.Write(content); err != nil {
        log.Fatal(err)
    }

    if _, err := tmpfile.Seek(0, 0); err != nil {
        log.Fatal(err)
    }

    oldStdin := os.Stdin
    defer func() { os.Stdin = oldStdin }() // Restore original Stdin

    os.Stdin = tmpfile
    if err := userInput(); err != nil {
        t.Errorf("userInput failed: %v", err)
    }

    if err := tmpfile.Close(); err != nil {
        log.Fatal(err)
    }
}

运行测试,我们看到一个输出:

What is your name?
Entered: Tom
PASS

简单,首选的方式

另请注意,您可以重构userInput()为不读取os.Stdin,但是可以接收io.Reader到读取的内容。这将使它更健壮并且更容易测试。

在您的应用程序,你可以简单地传递os.Stdin给它,并在测试中,你可以通过任何io.Reader它创建/在测试准备,例如使用strings.NewReader()bytes.NewBuffer()bytes.NewBufferString()



 类似资料:
  • 你有时能看到用另一种不同的接口(不同参数和返回值)实现addTime这样的函数。addTime函数不是在每次调用时都创建一个新对象,而是要求调用者提供一个“空对象”用以存储其结果。请将下述代码和之前版本做比较: void addTimeFill (const Time& t1, const Time& t2, Time& sum) { sum.hour = t1.hour + t2.hou

  • 我正在为类创建一个EMPLOYeE记录文件的程序。我创建了两个结构。一个叫做雇员,一个叫做日期。EMPLOYeE结构有一个字符数组、一个int、6个浮点值和DATE(另一个结构)。DATE结构只有三个int值(月、日、年)。 我创建了一个名为person[1000]的EMPLOYEE类型数组。 这是我的代码,我一直得到一个调试断言失败的错误,在可视化工作室指向fWrite. c表达式:(流!=NU

  • 我正在使用Debezium Postgres连接器。我在Postgres中有两个表,分别命名为'publications'和'comments'。根据标准示例,kafka和zookeeper运行在docker容器中。postgres正在本地运行。在使用debezium postgres connect之后,我有以下主题: __consumer_offsets dbserver1.public.co

  • 问题内容: 从问题的答案如何对varchar []使用array_agg() , 我们可以创建一个自定义的聚合函数来聚合Postgres中的n维数组,例如: 一个约束是值必须共享 相同的数组范围和相同的长度 ,处理空值和不同的长度是行不通的。 从答案: 没有办法解决,数组类型不允许在Postgres中出现这种不匹配的情况。您可以使用NULL值填充数组,以便所有维都具有匹配范围。 我有像这样的行 我

  • 但是,当我运行使用maven从命令行生成的jar时,它不会读取application.properties,默认情况下,tomcat是在8080上启动的,我无法识别上下文。其他的一切都很好。 在eclipse中,我将:VM参数提供为: 我文章和问题看起来很相似,我已经引用了这篇文章,只有我引用了Application.Properteis来配置spring boot应用程序的自定义上下文和端口。我

  • 和一个类ContentProvider,因为它也是在日志中的错误中指定的 公共类PoemsProvider扩展ContentProvider{private static final UriMatcher URI_MATCHER=new UriMatcher(UriMatcher.no_match);private static final int peams=1;private static f