【问题标题】:Strict mode for Akka TestKit probesAkka TestKit 探针的严格模式
【发布时间】:2017-03-26 22:53:57
【问题描述】:

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

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() 不是解决方案)

【问题讨论】:

    标签: scala akka actor akka-testkit


    【解决方案1】:

    对于测试失败的东西,它必须抛出执行测试的某种线程的断言错误,但由于探针是异步的,因此您放入其中的任何故障检测都将发生在不同的线程上,因此存在必须是您从测试中调用方法的地方(就像expectNoMsg())。

    话虽如此,您仍然可以对这个概念进行抽象,例如挂钩到您的测试工具包中。

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

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

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

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

    【讨论】:

    • 感谢您的解释 - 虽然我做了一些稍微不同的事情(expectNoMsg(0 seconds) 用于夹具拆卸的所有探针),但它绝对受到了这个答案的启发。
    猜你喜欢
    • 2019-12-19
    • 2019-12-10
    • 1970-01-01
    • 2014-04-18
    • 1970-01-01
    • 2021-08-25
    • 1970-01-01
    • 2021-03-17
    • 2017-10-13
    相关资源
    最近更新 更多