我正在使用akka testkit和scalatests来运行我的测试,这是我的代码
class MyTest extends (ActorSystem("testsystem")) /*with AsyncWordSpec*/ with ImplicitSender with AnyWordSpecLike with Matchers with BeforeAndAfterAll {
"an actor test" must {
val probe = TestProbe()
val myActor1 = TestActorRef[MyActor]
"send back messages " in {
probe.send(myActor1,Found(id = "234"))
probe.expectMsg(true)
//i want to get the future value like this as well
val future = ask(myActor, Found(id = "234")).mapTo[Boolean]
future onComplete {
case Success(somevalue) => info("oncomplete returned result is " + somevalue)
case Failure(ex) =>throw ex
}
}
}
class MyActor extends Actor {
def receive: PartialFunction[Any, Unit] = {
case Found(id) =>
log.info("received message {}", id)
sender() ! true
case message =>
unhandled(message)
}
}
现在的问题是上面的代码工作正常,但未来的完整部分有时会执行,有时不会,当运行测试时,我研究了异步测试scala,并试图实现示例http://www.scalatest.org/user_guide/async_testing
因此,我需要从任何一个给定的类扩展,我选择了AsyncWordSpec
,这样我就可以运行异步测试,每次都可以得到future的值,但是我已经从TestKit
类扩展了,我不能从抽象类AsyncWordSpec
扩展,所以我如何才能让它工作呢?
2条答案
按热度按时间iswrvxsc1#
问题是你的
future
需要等待,以确保它被执行。future在异步创建的那一刻开始求值。这意味着主线程在未来完成之前不会被阻塞--它会继续运行。所以,在你的情况下有两种可能性:在第二种情况下,由于测试退出时的未来终止,回调不会运行。为了使这件事更可预测,您应该在测试结束时阻塞结果的未来。您可以使用test framework sugar或
Await.result
来实现这一点。ttisahbt2#
一些澄清:
阻塞运行测试的单个线程直到将来完成是好的,在异步测试用例中没有任何价值。测试线程与Akka中的线程/调度器是分开的,在那里阻塞会有问题。
例如,当您执行
expectMessage
时,TestKit探测器会在完成时阻塞。Await.result
是单向的,Scalatest也有ScalaFutures
,它向Future
添加了一个装饰器,称为.futureValue
和.whenReady
,这两个装饰器也会阻塞测试线程,直到将来完成或达到超时。