Akka TestKit如何等待消息被处理

Akka TestKit how to wait for the message to be processed

在我的 TestKit 测试中

"A History Actor" must {

    // given
    val historyActorRef = TestActorRef(new HistoryActor("history-file.log"))       // Creation of the TestActorRef
    val writerActorRef = TestActorRef(new WriterActor("history-file.log"))       // Creation of the TestActorRef

    historyActorRef.underlyingActor.writerActor = writerActorRef

    "receive messages and change state" in {  // integration-like test

      // This call is synchronous. The actor receive() method will be called in the current thread

      // when
      historyActorRef ! WriteMsg("line 1")

      // then (1) - got WriteResult (from WriterActor as result of getting WriteMsg)
      within(200 millis) {
        expectMsg(WriteResult(1, 7))
      }

      // then (2) - state
      historyActorRef.underlyingActor.lastWrite must equal(WriteResult(1,7)) // With actorRef.underlyingActor, we can access the react actor instance created by Akka
    }
  }

这个测试失败了,因为它仍然是WriteResult(0,0)

在我的工作中的方式 HistoryActor:

   case cmd: WriteMsg => {

      log.info("forwarding " + cmd + " to the writer" )

      writerActor ! cmd

    }

    case result: WriteResult => {

      log.info("WriteResult: " + result)

      lastWrite = result                  // update the state

    } 

那么,当我们检查结果的时候,如何做测试来确保WriteResult已经处理了呢?

P.S。 我想我应该考虑单独测试 WriterActor,但假设我想要类似集成的测试。

如果您还没有这样做,则需要在 TestActorRef 中将两个被测试的参与者包装在此处。这将确保两者都使用调用线程分派器来消除测试场景中的异步性。您还可以考虑将 writeActor 替换为 TestProbe 进行测试,然后模拟它的行为。

更新

根据我的评论:

当你说 expectMsg 时你在说的是测试本身(由 TestKit 引入的隐式发送者)正在从它最初发送的消息中接收响应消息以启动考试。我认为这不是您要断言的内容,因此我建议您将其删除。我认为您是想说写入演员收到了该消息,但这不是测试套件断言的工作方式。只需验证内部状态是否已更新就足够了