【问题标题】:How to mock scala readLine如何模拟sc​​ala readLine
【发布时间】:2015-04-06 15:36:54
【问题描述】:

我想为我的 main 函数编写一个单元测试,其中有一个 readLine() 循环。

我已经尝试过以下基于 java 的。我认为readLine() 可能需要System.in 作为inputStream。但它不起作用。 ScalaTest 在 readLine() 等待输入时被阻止。

"readLine" should "work" in {
  val in = new ByteArrayInputStream("abc".getBytes)
  System.setIn(in)
  readLine() === "tester"
}

有什么想法吗?谢谢。

【问题讨论】:

  • 我不太清楚你的问题。您是否正在寻找一种更好的阅读台词的方法? io.Source.fromInputStream(...).getLines 可以从输入流中读取,非常容易使用或传递不同的流。
  • readLine 是什么 - 这是 scala.Console 或 scala.io.StdIn 中已弃用的方法吗?或者这是你自己创造的功能?如果有,能否发一下出处?
  • @soong, @rock-fall 抱歉,问题不清楚。我想要做的是集成测试并模拟用户输入以验证我的应用程序的行为是否正确。由于有一些电话,如console.readLine() 等,我想模拟它们,例如在Inputbuffer 中预先添加一些字符串作为用户输入。然后,readLine() 只是从这个InputBuffer 读取输入。
  • 简而言之,在上面的sn-p代码中,readLine()应该返回“abc”。
  • 我理解那部分,但我认为您遇到的问题是 readLine 的工作方式。如果它设置为使用System.in你调用setIn,那么它已经有对原始输入流的引用。如果您使用的是scala.Console,则有一些方法可以在该类中设置新的输入流,这应该可以解决您的问题。 (遗憾的是,scala.io.StdIn 依赖于 scala.Console,但没有指定输入流的固有方法,尽管子类可以这样做)。

标签: scala mocking inputstream


【解决方案1】:

单元测试的正确方法是遵循"ports and adapters" 模式。

所以你应该有一个接口,它是控制台阅读器的“端口”,这样你就可以在你的单元测试中模拟它。

此外,您应该有一个集成测试,以验证您的“适配器”是否确实适用于真实的控制台。

根据您的问题标题,我猜您想进行集成测试。你快到了。您调用了自 Scala 2.11.0 以来已弃用的弃用方法。这段代码应该可以工作 -

"readLine" should "work" in {
  val in = new ByteArrayInputStream("abc".getBytes)
  System.setIn(in)
  StdIn.readLine() === "abc"
}

【讨论】:

    【解决方案2】:

    Maxim 的解决方案实际上对我不起作用(现在?)。因此,为了帮助面临同样问题的其他人:

    val in = new ByteArrayInputStream(("abc").getBytes)
    
    Console.withIn(in)  {
        assert(StdIn.readLine() === "abc")
    }
    

    【讨论】:

    • 非常方便。我的 sbt 测试循环最终卡住了使用 Maxim 的解决方案请求输入。
    猜你喜欢
    • 2019-06-01
    • 1970-01-01
    • 2012-11-27
    • 1970-01-01
    • 2017-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多