如何测试 scalaz IO?

How to test scalaz IO?

考虑以下 IO:

val io = (for{
      userChoice <- getChar
    } yield if (userChoice == 'y') putStr("yes") else putStr("no")).flatMap(identity)

我正在尝试这样测试它:

    val input: InputStream = new ByteArrayInputStream(Array('n', 'n')) // Not sure why I need two of them...
    System.setIn(input)
    val output = new ByteArrayOutputStream()
    System.setOut(new java.io.PrintStream(output))
    io.unsafePerformIO()
    System.setIn(new FileInputStream(FileDescriptor.in))
    System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out)))
    output.toString ==== "no"

我在 sbt 中使用 specs2 进行测试。我第一次 运行 测试,它通过了。第二次它失败并显示 Console has reached end of input 并且 sbt 处于一种奇怪的状态,我需要杀死它。

我想可能与 sbt 有某种交互,但我不明白它到底是什么。有没有更好的方法来测试IO?

对于这种交互,我认为值得使用 Free monads 开发一个 "mini-language" 并有 2 个解释器,一个用于使用 Id Monad 进行测试,另一个用于生产使用IO 单子。

来自文档 "Forking" 部分的 Configuring Input

By default, the standard input of the sbt process is not forwarded to the forked process. To enable this, configure the connectInput setting:

connectInput in run := true