我正在为基于参与者的应用程序编写一个测试用例。其中一个组件可以大致定义如下:
class MyActor(a: ActorRef, b: ActorRef) extends Actor {
override def receive: Receive = {
case _ =>
a ! "Got message!"
b ! "Hello!"
}
}现在,为了编写测试用例,我使用了akka-testkit和TestProbe。测试用例的一个重要部分如下:
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,从而使每条消息都被某种方式期望?更好的方法是通过TestKit、ActorSystem或TestProbe配置,但是任何不需要修改每个测试用例的解决方案都可以(因此在每个通信结束时调用expectNoMsg()并不是一个解决方案)。
发布于 2017-04-03 13:59:17
要使测试失败,它必须抛出执行测试的某种线程的断言错误,但是由于探测是异步的--您输入的任何故障检测都将发生在不同的线程上,因此需要有一个地方从测试中调用方法(就像expectNoMsg()一样)。
尽管如此,您仍然可以抽象出这个概念,例如,连接到您的测试工具包中。
一种可能的方法是使用高阶函数:
def failOnUnexpectedMessage[T](test: ActorRef => T): T = {
val probe = TestProbe()
val result = test(probe.ref)
probe.expectNoMsg()
result
}然后,您可以在您的测试中使用它(这里的Scalatest word规范样式):
"My actor" should {
"something something" in failOnUnexpectedMessage { ref =>
val actor = ...construct and pass it ref as b...
...rest of the test...
}
}https://stackoverflow.com/questions/43035532
复制相似问题