StackOverflow сообщение, которое Вы упомянули содержит два предложили способы проверки вашего актера.
- Излучение государства переходит к другому актеру.
- Не тестируйте изменение состояния, но поведение актера.
В первом примере у вас есть способ отправить информацию из вашего актера при каждом изменении состояния. В Акке передача информации об изменении состояния в качестве сообщений актеров является естественным способом реализации этого.
import akka.actor._
import akka.testkit._
class ExampleActor(notify: ActorRef) extends Actor with ActorLogging {
import ExampleActor.{Master, StandBy}
def receive: Receive = master
def master: Receive = {
case StandBy =>
notify ! StandBy
context.become(standby)
case msg =>
log.debug("received msg in master: {}", msg)
}
def standby: Receive = {
case Master =>
notify ! Master
context.become(master)
case msg =>
log.debug("received msg in standby: {}", msg)
}
}
object ExampleActor {
def props(notify: ActorRef): Props = Props(new ExampleActor(notify))
case object Master
case object StandBy
}
class ExampleActorTest extends TestKit(ActorSystem("testSystem")) with FlatSpecLike {
"ExampleActor" should "move to stand by state" in {
val probe = TestProbe()
val actor = system.actorOf(ExampleActor.props(probe.ref))
actor ! ExampleActor.StandBy
probe.expectMsg(ExampleActor.StandBy)
}
}
(Я не запускать код еще не так извинения за любые ошибки в коде)
В приведенном выше коде, ExampleActor
является состоянием актера, который уведомляет данную ссылку актера каких-либо изменений состояния , Обратите внимание, что это не позволяет проверять текущее состояние, а вместо этого - журнал состояний. Кроме того, можно ввести ошибку в коде уведомления штата, потому что код уведомления вручную добавляется к актеру, а не актер делает это автоматически.
Я изменил стиль тестирования на asynchronous testing style, чтобы получить более реалистичные тесты.
Уведомления об изменении состояния позволяют получать информацию о том, какое конкретное состояние переходит на актер, но он не говорит вам, работает ли он так, как должно. Вместо того, чтобы проверять, какие изменения состояния проходит актер, как насчет тестирования того, что делает сам актер.
class Accumulator extends Actor with ActorLogging {
import Accumulator._
def receive: Receive = accumulatorReceive(0)
def accumulatorReceive(x: Int): Receive = {
case Add(i) => next(x + i)
case Remove(i) => next(x - i)
case Multiply(i) => next(x * i)
case Divide(i) => next(x/i)
case Get => sender() ! x
}
def next(x: Int) = context.become(accumulatorReceive(x))
}
object Accumulator {
def props: Props = Props(new Accumulator)
case class Add(i: Int)
case class Remove(i: Int)
case class Multiply(i: Int)
case class Divide(i: Int)
case object Get
}
class AccumulatorTest extends TestKit(ActorSystem("testSystem")) with FlatSpecLike {
import Accumulator._
"Accumulator" should "accumulate" in {
val probe = TestProbe()
val actor = system.actorOf(Accumulator.props)
actor ! Add(3)
actor ! Remove(1)
actor ! Multiply(4)
actor ! Divide(2)
probe.send(actor, Get)
probe.expectMsg(5)
}
}
В этом примере Accumulator
делает изменение состояния, но не уведомляет, когда его состояние изменилось. Вместо этого у него есть специальная команда для проверки интересных деталей о ее состоянии. В тесте мы отправляем несколько сообщений, которые вызывают изменения состояния актера аккумулятора. Наконец, мы проверяем результат этих сообщений, запрашивая аккумулятор.
Рассмотрите возможность использования [Akka Finite State Machine] (http://doc.akka.io/docs/akka/current/scala/fsm.html) вместо попытки «запретить». –