有没有办法在 Actor 的接收定义中获取“存储”值?

时间:2021-03-23 00:37:49

标签: scala testing akka actor

我希望能够对“存储”到我的演员的 Receive 函数中的值进行断言。有没有办法用任何 Akka 测试库来做到这一点?

在下面的示例中,我想获取 currentCount

import akka.actor.Actor

class CounterActor extends Actor {
  import CounterActor._
  
  override def receive: Receive = count(0) 

  def count(currentCount: Int): Receive = { 
    case Increment => context.become(count(currentCount + 1))
    case Decrement => context.become(count(currentCount - 1))
  }
}

object CounterActor {
  case object Increment
  case object Decrement
}

然后我想用一个 Test 类来反对它:

val counterActorRef = TestActorRef(new CounterActor())

"A counter actor" should {
  "have a count of 3" in {
    counterActorRef ! CounterActor.Increment
    counterActorRef ! CounterActor.Increment
    counterActorRef ! CounterActor.Increment
    
    val counterValue = // obtain currentCount from counterActorRef
    assert(counterValue == 3)
  }
}

我尝试过使用 TestActorRef,但没有成功。我知道有一种方法可以通过添加消息案例来获取它,或者添加一些调试/信息级别的日志消息并使用 EventFilter 来满足这一点。是否有使用我不知道的测试库获取它的简单方法?

我已经在 akka.testkit 库中搜索了一段时间,但找不到我的解决方案。

感谢任何帮助,谢谢。

2 个答案:

答案 0 :(得分:0)

您想要做什么 - ask 演员关于他的状态并在测试中 assert 它。 第一步——读取值:

import akka.actor.Actor

class CounterActor extends Actor {
  import CounterActor._
  
  override def receive: Receive = count(0) 

  def count(currentCount: Int): Receive = { 
    case Increment => context.become(count(currentCount + 1))
    case Decrement => context.become(count(currentCount - 1))
    case Read => sender() ! 
  }
}

object CounterActor {
  case object Increment
  case object Decrement
  case object Read
  case class CurrentValue(currentCount: Int) //for type safety
}

第二步 - 在测试中断言:

val counterActorRef = TestActorRef(new CounterActor())

"A counter actor" should {
  "have a count of 3" in {
    counterActorRef ! CounterActor.Increment
    counterActorRef ! CounterActor.Increment
    counterActorRef ! CounterActor.Increment
    
    val counterValue = (counterActorRef ? Read).futureValue
    assert(counterValue == CurrentValue(3))
  }
}

答案 1 :(得分:0)

演员模型有两个特点:

  • actor 状态的封装是激进的,并且(在 JVM 上,有效地(因为可能通过反射破坏封装))是完整的。

  • 观察到参与者的状态仅在其行为(它如何响应消息,以及在 Akka(它不是“一直向下的参与者”)的情况下)它执行的副作用方面才重要) 因该状态而变化。

为了验证状态转换是否发生,您只能测试它的行为是否符合预期。公开查询消息是一种方法;诸如点击日志条目流或(如果是事件源,则是持久性事件流)之类的东西。

也就是说,仅出于启用可测试性的目的而公开查询消息通常不是可行的方法(这可能对操作调试有用)。理想的情况是测试参与者响应状态变化的“带内”行为(例如,“在发送 A 为真的消息后,对 B 为真的消息的响应表现出属性 C”)。如果状态变化没有以某种方式表现为行为变化,为什么状态变化会发生?

换句话说,将其他参与者视为黑盒服务通常是好的。如果您正在测试 SO,则无法验证“发布问题后,数据库中的此字段设置为此值”(因为您作为用户无权访问数据库,并且您无法提供您控制的模拟 SO)。您可以验证的是“当我发布问题时,我会返回一个问题 ID,当我请求该 ID 时,我会返回问题的内容”。

相关问题