时间:2019-07-02 21:34:03

标签: scala akka stdout scalatest testkit

我正在编写一个UCI解释器,作为Akka有限状态机。根据规范,解释器必须将其输出写入stdout,并从stdin获取输入。

我有一个针对演员的测试服,可以测试其行为的某些方面(与消息相关),但是我不知道如何捕获stdout进行断言,也不知道如何发送它其通过stdin的输入。我已尽我所能探索了scalatest API,但找不到如何实现所需的功能。

这是当前的测试课程:

package org.chess

import akka.actor.ActorSystem
import akka.testkit.{TestKit, TestProbe}
import org.chess.Keyword.Quit
import org.scalatest.wordspec.AnyWordSpecLike
import org.scalatest.{BeforeAndAfterAll, Matchers}

import scala.concurrent.duration._
import scala.language.postfixOps

class UCIInterpreterSpec(_system: ActorSystem)
  extends TestKit(_system)
    with Matchers
    with AnyWordSpecLike
    with BeforeAndAfterAll {

  def this() = this(ActorSystem("UCIInterpreterSpec"))

  override def afterAll: Unit = {
    super.afterAll()
    shutdown(system)
  }

  "A UCI interpreter" should {

    "be able to quit" in {
      val testProbe = TestProbe()
      val interpreter = system.actorOf(UCIInterpreter.props)
      testProbe watch interpreter
      interpreter ! Command(Quit, Nil)
      testProbe.expectTerminated(interpreter, 3 seconds)
    }

  }

}

当然,知道解释器可以退出是有用的……但不是很有用。我需要测试,例如,如果将字符串isready发送到解释器,它将返回readyok

是否可能通过使用akka.testkit而不是更简单的框架来使测试过于复杂?为了简单起见,我想继续使用单个测试框架,并且我需要测试系统中许多其他与actor相关的元素,因此,如果可以在不离开akka-testkit / scalatest域的情况下解决该问题,那就太好了。

任何帮助将不胜感激。预先感谢。

1 个答案:

答案 0 :(得分:4)

您需要更改Actor的设计。

演员不应直接阅读stdin或直接写stdout。而是在Props中给actor对象提供输入并接受输出。 stdin可能类似于() => String,每次需要输入时都会调用。 stdout可以是每次生成输出时都会调用的String => Unit。或者,您可以使用Streams或类似的构造为抽象数据源和数据宿的结构。

在生产代码中,您传递使用stdinstdout的对象,但是对于测试代码,您传递读取和写入内存缓冲区的对象。然后,您可以检查Actor是否消耗了适当的输入,并且Actor是否产生了适当的输出。