TestKit,测试类必须继承几个接口:
class SendingActor01Test extends TestKit(ActorSystem("testsystem")) //TestKit创建testsystem用于测试
with WordSpecLike //可以用must,in等语句描述测试方法
with MustMatchers //must描述assertion,比如"hello" must (contain("hello"))
with StopSystemAfterAll { //保证所有测试结束后关闭system
"A Silent Actor" must { //测试的文本规范
"change state when it receives a message, single threaded" in { //每个in内是具体的测试内容
//Write the test, first fail
fail("not implemented yet")
}
"change state when it receives a message, multi-threaded" in {
//Write the test, first fail
fail("not implemented yet")
}
}
}
这些接口帮我们实现初始化actor testsystem,testActor,测试结束清理.
测试环境分为:
- 单线程
- 多线程
- 多JVM
单线程
这个环境下,我们一般是简单的测试,使用TestActorRef允许我们直接访问silentActor内部
//单线程环境
"A Silent Actor" must {
"change internal state when it receives a message, single" in {
import SilentActorProtocol._
//actor是不能直接访问的,所以使用TestActorRef允许我们直接访问silentActor内部
val silentActor = TestActorRef[SilentActor]
silentActor ! SilentMessage("whisper")
//直接调用silentActor的内部状态,也可以直接调用内部方法
silentActor.underlyingActor.state must (contain("whisper"))
}
}
TestActorRef和LocalActorRef,使用只做测试用的CallingThreadDispatcher作为调度器,CallingThreadDispatcher不会在新线程中调用actor
多线程环境
由于不能直接访问actor,我们只能通过testActor获取actor的message,比如:
//多线程下测试,不能直接访问actor内部,所以通过testActor做消息的中转
"A Silent Actor" must {
"change internal state when it receives a message, multi" in {
import SilentActorProtocol._
val silentActor = system.actorOf(Props[SilentActor], "s3")
silentActor ! SilentMessage("whisper1")
silentActor ! SilentMessage("whisper2")
//silentActor将处理结果发送给testActor
silentActor ! GetState(testActor)
//expectMsg方法获取testActor收到的message
expectMsg(Vector("whisper1", "whisper2"))
}
expectMsg,expectMsgPF方法接受来自test actor的消息。所以当要测试一个actor相应的message,可以将消息发送给testActor,testActor转发到我们的测试方法。
多JVM环境
discuss on chapter 5
我们归类一下actor,有如下三种:
1. SilentActor
不返回,不发送message。我们要测试它是否接受到了message,知否改变了内部状态,是否抛出异常。
对于单线程环境,我们用TestActorRef就可以。多线程环境我们还是要用testActor。
2. SendingActor
会发送message给其他的actor,一般我们测试将其作为黑盒.使用testActor接受消息,并使用expectMsg或者expectMsgPF从testActor获取从被测试actor收到的message。
3.SideEffectingActor
接受一个message,并与一些object交互。当我们发送message给它时,要检测object是变动
TestProbe
TestKit提供了testActor,我们使用:
- expectMsg
- expectNoMsg
- ignoreMsg
- expectMsgPF
等方法来获取testActor接受的message.如果我们要接受发送给多个actor的message,我们就要用TestProbe了,直接调用TestProbe()
即可
总结
大多数情况下,使用testActor测试是最方便的。