scala - 将 futures 与 actor 消息混合时确保测试中的消息顺序

标签 scala testing akka actor akka-testkit

我正在测试一个使用基于 future 的异步 API 的参与者。当 future 完成时,参与者使用管道模式向自己发送消息:

import akka.pattern.pipe
// ...

// somewhere in the actor's receive method
futureBasedApi.doSomething().pipeTo(self)

在我的测试中,我模拟了 API,因此我通过 promise 控制 future 的完成。然而,这与直接发送给参与者的其他消息交织在一起:

myActor ! Message("A")
promiseFromApiCall.success(Message("B"))
myActor ! Message("C")

现在我想知道如何保证 Actor 收到并 在我的测试中在消息A和C之间处理消息B,因为消息B实际上是在另一个线程中发送的,所以我无法控制顺序 Actor 的邮箱在其中接收消息。

我考虑了几种可能的解决方案:

  • 在每条消息后休眠几毫秒,以便进行另一条消息 不太可能订购

  • 等待 actor 确认每条消息,尽管 只有测试需要确认

  • 将消息 B 直接发送给参与者以模拟完成 future 并编写一个单独的测试以确保管道模式 被正确使用(如果 Actor 愿意,上面的测试不会失败 不要将结果消息通过管道传递给自己)

我不太喜欢这两个选项,但我倾向于使用最后一个 一。有没有其他更好的方法可以在测试中强制执行特定的消息顺序?

澄清:问题不在于如何处理消息在生产中可能以随机顺序接收的事实。控制测试中的顺序对于确保参与者实际能够处理不同的消息顺序至关重要。

最佳答案

一个想法是在你的actor中定义一个标志,指示actor是否收到消息B。当actor收到消息C时,actor可以stash如果标志为假,则该消息 C,然后在 Actor 收到消息 B 后将其取消存储。例如:

class MyActor extends Actor with Stash {

  def receiveBlock(seenMsgB: Boolean, seenMsgC: Boolean): Receive = {
    case MakeApiCall =>
      callExternalApi().mapTo[MessageB].pipeTo(self)

    case m: MessageB if seenMsgC => // assume msg C has been stashed
      unstashAll()
      // ...do something with msg B
      become(receiveBlock(true, seenMsgC)) // true, true
    case m: MessageB if !seenMsgC =>
      // ...do something with message B
      become(receiveBlock(true, seenMsgC)) // true, false

    case m: MessageC if seenMsgB =>
      // ...do something with message C
      context.become(receiveBlock(seenMsgB, true)) // true, true
    case m: MessageC if !seenMsgB =>
      stash()
      context.become(receiveBlock(seenMsgB, true)) // false, true

    case ...
  }

  def receive = receiveBlock(false, false)
}

关于scala - 将 futures 与 actor 消息混合时确保测试中的消息顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51241038/

相关文章:

scala - 查询参数作为列表

asp.net - 测试如何与 ASP.NET MVC/WEBFORMS Silverlight MVVM 相关

sql-server - tSQLt TRUSTWORTHY 和 CLR 要求

java - Akka 。如何使用 Source.actorRef 完成流?

scala - akka 类 Receive 定义在哪里?

scala - 在测试中获取用于在 Akka 中创建 actor 的类实例

Scala 通过表达式向数据框添加新列

java - Scala/Java 中的简单、无忧、零样板序列化,类似于 Python 的 Pickle?

scala - 猫 : mapping over tuples with the same applicative

testing - 如何对网站进行负载测试?