classBasicSpecextendsTestKit(ActorSystem("BasicSpec")) withImplicitSender withWordSpecLike withBeforeAndAfterAll { // setup overridedefafterAll(): Unit = { TestKit.shutdownActorSystem(system) } importBasicSpec._ // message assertions "A lab test actor" should { val labTestActor = system.actorOf(Props[LabTestActor]) "turn a string into uppercase" in { labTestActor ! "I love Akka" val reply = expectMsgType[String] assert(reply == "I LOVE AKKA") } "reply to a greeting" in { labTestActor ! "greeting" expectMsgAnyOf("hi", "hello") } "reply with favorite tech" in { labTestActor ! "favoriteTech" expectMsgAllOf("Scala", "Akka") } "reply with cool tech in a different way" in { labTestActor ! "favoriteTech" val messages = receiveN(2) // Seq[Any] // free to do more complicated assertions } "reply with cool tech in a fancy way" in { labTestActor ! "favoriteTech" expectMsgPF() { case"Scala" => // only care that the PF is defined case"Akka" => } } } }
testProbe (测试探针)
A test probe is essentially a queryable mailbox which can be used in place of an actor and the received messages can then be asserted
"A master actor" should { "register a slave" in { val master = system.actorOf(Props[Master]) val slave = TestProbe("slave") master ! Register(slave.ref) expectMsg(RegistrationAck) } "send the work to the slave actor" in { val master = system.actorOf(Props[Master]) val slave = TestProbe("slave") master ! Register(slave.ref) expectMsg(RegistrationAck) val workloadString = "I love Akka" master ! Work(workloadString) // the interaction between the master and the slave actor slave.expectMsg(SlaveWork(workloadString, testActor)) slave.reply(WorkCompleted(3, testActor)) expectMsg(Report(3)) // testActor receives the Report(3) } "aggregate data correctly" in { val master = system.actorOf(Props[Master]) val slave = TestProbe("slave") master ! Register(slave.ref) expectMsg(RegistrationAck) val workloadString = "I love Akka" master ! Work(workloadString) master ! Work(workloadString) // in the meantime I don't have a slave actor slave.receiveWhile() { caseSlaveWork(`workloadString`, `testActor`) => slave.reply(WorkCompleted(3, testActor)) } expectMsg(Report(3)) expectMsg(Report(6)) } }
"A worker actor" should { val workerActor = system.actorOf(Props[WorkerActor]) "reply with the meaning of life in a timely manner" in { within(500 millis, 1 second) { workerActor ! "work" expectMsg(WorkResult(42)) } } "reply with valid work at a reasonable cadence" in { within(1 second) { workerActor ! "workSequence" val results: Seq[Int] = receiveWhile[Int](max=2 seconds, idle=500 millis, messages=4) { caseWorkResult(result) => result } assert(results.sum > 5) } } "reply to a test probe in a timely manner" in { within(1 second) { val probe = TestProbe() probe.send(workerActor, "work") probe.expectMsg(WorkResult(42)) // timeout of 0.3 seconds } } }
"A checkout flow" should { "correctly log the dispatch of an order" in { EventFilter.info(pattern = s"Order [0-9]+ for item $item has been dispatched.", occurrences = 1) intercept { // our test code val checkoutRef = system.actorOf(Props[CheckoutActor]) checkoutRef ! Checkout(item, creditCard) } } "freak out if the payment is denied" in { EventFilter[RuntimeException](occurrences = 1) intercept { val checkoutRef = system.actorOf(Props[CheckoutActor]) checkoutRef ! Checkout(item, invalidCreditCard) } } }
classFulfillmentManagerextendsActorwithActorLogging{ var orderId = 43 overridedefreceive: Receive = { caseDispatchOrder(item: String) => orderId += 1 log.info(s"Order $orderId for item $item has been dispatched.") sender() ! OrderConfirmed } }
可以控制日志的级别,还可以对异常进行拦截
1 2 3 4 5 6
"freak out if the payment is denied" in { EventFilter[RuntimeException](occurrences = 1) intercept { val checkoutRef = system.actorOf(Props[CheckoutActor]) checkoutRef ! Checkout(item, invalidCreditCard) } }
"A counter" should { "synchronously increase its counter" in { val counter = TestActorRef[Counter](Props[Counter]) counter ! Inc// counter has ALREADY received the message assert(counter.underlyingActor.count == 1) } "synchronously increase its counter at the call of the receive function" in { val counter = TestActorRef[Counter](Props[Counter]) counter.receive(Inc) assert(counter.underlyingActor.count == 1) } "work on the calling thread dispatcher" in { val counter = system.actorOf(Props[Counter]) val probe = TestProbe() probe.send(counter, Read) probe.expectMsg(Duration.Zero, 0) // probe has ALREADY received the message 0 } }