Akka Actors傻瓜单元测试

Ser*_*iGP 5 unit-testing scala akka scalatest akka-testkit

我是Akka和Scala的新手,我来自一个并发的世界。可能我做错了很多事情,即使与问题无关,我也会感谢您的反馈。

我正在用Akka和Scala做一个简单的聊天应用程序。我从“键入功能”开始(不列颠哥伦比亚省的业务要求)...这是whatsapp或“约翰正在键入消息”的典型功能。

我已经使用两种参与者类型对它进行建模:对话者和对话,并且我想对对话参与者进行单元测试。我的对话演员看起来像这样:

object Conversation {
  def props(conversationId: UUID, talkers: List[ActorRef])(out: ActorRef) = Props(new Conversation(conversationId, talkers))

  case class Typing(talkerId: TalkerId)
}

class Conversation(conversationId: UUID, talkers: List[ActorRef]) extends Actor with ActorLogging {
  def receive = LoggingReceive {
    case Typing(talkerId) =>
      // notify all talkers that a talker is typing
      // @TODO don't notify user which is typing
      talkers foreach {talker: ActorRef => talker ! InterlocutorTyping(talkerId)}
 }
}
Run Code Online (Sandbox Code Playgroud)

我认为,到现在为止很简单。因此,在开始使用Scala和Akka进行编码之前,我已经进行了如下测试:

  • 我得到了对话演员
  • 我嘲笑说话者
  • 我发送信息给演员
  • 我希望应该通知说话者

我真的不知道在Scala和Akka中这是否是正确的方法。我的测试(使用scalatest)如下所示:

"Conversation" should {
"Notify interlocutors when a talker is typing" in {
  val talkerRef1 = system.actorOf(Props())
  val talkerRef2 = system.actorOf(Props())

  val talkerRef1Id = TalkerIdStub.random

  val conversationId = UUID.randomUUID()

  val conversationRef = system.actorOf(Props(classOf[Conversation], conversationId, List(talkerRef1, talkerRef2)))

  // should I use TestActorRef ?

  conversationRef ! InterlocutorTyping(talkerRef1Id)

  // assert that talker2 is notified when talker1 is typing
}
}
Run Code Online (Sandbox Code Playgroud)
  1. 我应该使用TestActorRef吗?我应该使用TestProbe()(我读到这是用于集成测试)

  2. 如何创建Talker模拟?这种方法正确吗?

  3. 将对话者列表插入我的对话演员是正确的吗?

我搜索了文档,但是我认为文档太旧了,我不确定代码示例是否仍然有效。

谢谢您的宝贵时间,对于这个菜鸟问题表示歉意:=)

jaz*_*mit 3

确实,Akka 中的测试情况至少可以说有点令人困惑。

在 Akka 中,通常有两种测试:同步测试和异步测试,有些人将其称为“单元”测试和“集成”测试。

  • “单元测试”是同步的,您可以直接测试接收方法,而不需要参与者系统等。在您的情况下,您需要模拟List[Talkers],调用您的receive方法并验证发送方法是否被调用。你可以直接实例化你的actor new Conversation(mockTalkers),在这种情况下没有必要使用TestActorRef。对于模拟,我推荐ScalaMock

  • “集成测试”是异步的,通常测试多个参与者一起工作。您可以在此处继承TestKit、实例化TestProbes 作为您的谈话者,使用其中一个向Conversation参与者发送消息,并验证另一个接收到该InterlocutorTyping消息。

您认为哪种测试合适取决于您。我个人的观点是,除非您的参与者有复杂的内部行为,否则您应该跳过同步测试并直接进行异步(“集成”)测试,因为这将涵盖您可能会错过的更棘手的并发边缘情况。它们也更加“黑匣子”,因此在您改进设计时对变化不太敏感。

文档页面上有更多详细信息和代码示例。