使用TestActorRef
执行同步测试时(根据Testing Actor Systems的建议),有时需要测试异常是否不抛出,与预期的任何其他测试分开要传回的消息等。
如何在单元测试中可靠地完成这项工作?
This answer显示了如何使用EventFilter
为异常添加处理程序。但是,此方法不适用于Throwable
的{{1}}。
以下是示例代码:
Error
此代码存在多个问题,但主要问题是第三个测试始终失败,因为用户监护人失败,并在日志记录输出中显示以下消息:
import akka.actor.{Actor, ActorLogging, ActorSystem, Props}
import akka.event.Logging
import akka.testkit.{EventFilter, ImplicitSender, TestKit, _}
import com.typesafe.config.{Config, ConfigFactory}
import org.scalatest.{FlatSpec, Matchers}
import scala.collection.mutable
object GreetingProtocol {
case class Greet(msg: String)
case object GreetWithNPE
case object GreetWithError
}
class ErrorLogger() {
val errors = mutable.ListBuffer[Logging.Error]()
val filter = EventFilter.custom {
case e: Logging.Error =>
errors += e
false
}
}
class Greeter extends Actor with ActorLogging {
import GreetingProtocol._
def receive = {
case Greet(who) => log.info(s"Hello $who")
case GreetWithError => ???
case GreetWithNPE => throw new NullPointerException("NPE")
}
}
class GreetingSpec extends FlatSpec with Matchers {
import GreetingProtocol._
def testEventListener(theFilter: EventFilter) = Props(new TestEventListener { addFilter(theFilter) })
def akkaConfiguration: Config = ConfigFactory.parseString(
"""
|akka {
| loglevel = DEBUG
| actor.debug {
| receive = on
| lifecycle = on
| event-stream = on
| }
| remote {
| log-sent-messages = on
| log-received-messages = on
| }
|}
|
""".stripMargin)
"a normal greeting" should "cause the test to succeed" in
new TestKit(ActorSystem("test", akkaConfiguration)) with ImplicitSender {
val errorLogger = new ErrorLogger()
system.eventStream.subscribe(system.actorOf(testEventListener(errorLogger.filter), "ErrorListener"), classOf[Logging.Error])
filterEvents(errorLogger.filter)({
val greeter = TestActorRef[Greeter]("Greeter")
greeter ! Greet("Bob")
})
shutdown()
withClue("errors logged") {
errorLogger.errors should have length 0
}
}
"a NullPointerException" should "be caught by the testing framework and not make the test succeed" in
new TestKit(ActorSystem("test", akkaConfiguration)) with ImplicitSender {
val errorLogger = new ErrorLogger()
system.eventStream.subscribe(system.actorOf(testEventListener(errorLogger.filter), "ErrorListener"), classOf[Logging.Error])
filterEvents(errorLogger.filter)({
val greeter = TestActorRef[Greeter]("Greeter")
greeter ! GreetWithNPE
})
shutdown()
withClue("errors logged") {
errorLogger.errors should have length 1
}
}
"an Error" should "be caught by the testing framework and not make the test succeed" in
new TestKit(ActorSystem("test", akkaConfiguration)) with ImplicitSender {
val errorLogger = new ErrorLogger()
system.eventStream.subscribe(system.actorOf(testEventListener(errorLogger.filter), "ErrorListener"), classOf[Logging.Error])
filterEvents(errorLogger.filter)({
val greeter = TestActorRef[Greeter]("Greeter")
greeter ! GreetWithError
})
shutdown()
withClue("errors logged") {
// Fails because the user guardian is shut down and the ErrorListener is gone with it
errorLogger.errors should have length 1
}
}
}
第三种情况可以做些什么,以便测试成功(即错误记录在错误列表中)?
还有另外两个小问题:
版本: