首页 文章

Akka TestKit探针的严格模式

提问于
浏览
1

我正在为基于actor的应用程序编写测试用例 . 其中一个组件可以大致定义如下:

class MyActor(a: ActorRef, b: ActorRef) extends Actor {
    override def receive: Receive = {
        case _ => 
            a ! "Got message!"
            b ! "Hello!"
    }
}

现在,写一个测试用例我正在使用 akka-testkitTestProbe . 测试用例的一个重要部分如下:

val a = TestProbe()
val b = TestProbe()
val c = system.actorOf(Props(new MyActor(a.testActor, b.testActor)))

c ! "Message!"
a.expectMsg("Got message!")

现在的问题是测试用例通过,即使发送到 b 的消息不是预期的,因此也没有经过验证 .

我知道我可以在测试案例的开头调用 b.expectNoMsg() 来处理这个特定的问题,但不知何故我认为这不是一个可扩展的方法(我必须在所有预期的调用之后每次添加它,这非常麻烦) .

所以我的问题是:是否有一个选项可以在严格模式下运行 akka-testkit ,这样每条消息都必须以某种方式预期?优选方式是通过 TestKitActorSystemTestProbe 配置,但任何不需要修改每个测试用例的解决方案都可以(因此在每次通信结束时调用 expectNoMsg() 不是解决方案)

1 回答

  • 2

    对于某些未通过测试的东西,它必须抛出执行测试的某种线程的断言错误,但是由于探针是异步的,所以您放入的任何故障检测都将发生在不同的线程上,因此需要从测试中调用方法的地方(就像 expectNoMsg() 一样) .

    话虽这么说,你仍然可以抽象出这个概念,例如挂钩你的测试工具包 .

    一种可能的方法是使用更高阶函数:

    def failOnUnexpectedMessage[T](test: ActorRef => T): T = {
      val probe = TestProbe()
      val result = test(probe.ref)
      probe.expectNoMsg()
      result
    }
    

    然后你可以在你的测试中使用它(这里是Scalatest word spec style):

    "My actor" should {
      "something something" in failOnUnexpectedMessage { ref => 
        val actor = ...construct and pass it ref as b...
        ...rest of the test...
      }
    }
    

相关问题