2016-04-14 3 views
3

В моем приложении Scala говорят, что у меня есть Актер A и Актер B. Я хочу разработать тестовый пример в ScalaTest, который позволит мне отправить сообщение Актеру A и посмотреть, какое сообщение он отправляет Актеру B, чтобы узнать, правильно ли обрабатывает его A и отправляет правильное сообщение B. Как бы это проверить? Мне потребовалось много времени, чтобы приготовить это самостоятельно ... но это, похоже, в основном работает.Скала и Акка - Тестирующие актеры как система с Аккой Testkit

class A extends Actor { ... } 

class B extends Actor { ... } 

class C(p: TestProbe) extends B { 
    override def receive = { 
    LoggingReceive { 
     case x => 
     println(x.toString) 
     p.ref ! x 
    } 
    } 
} 

case class MsgToB(...) 

// Spec class which extends TestKit 
"A" should { 
    "send the right message to B" { 
    val p = TestProbe() 
    val a = TestActorRef[A] 
    val c = TestActorRef(Props(new C(p))) 

    // Assume A has a reference to C. Not shown here. 
    a ! msg 
    // Assert messages 
    p.expectMsgType[MsgToB] 
    } 
} 

Это лучшее средство для этого? Есть ли более эффективная практика?

ответ

1

Мне кажется, что вы хотите проверить поведение актера A в изоляции. Для того, чтобы сделать это, вы должны быть в состоянии контролировать то, как актер А получает свою ссылку на актер В. Например, вы можете предоставить ссылку в конструкторе актера:

import akka.actor.{Actor, ActorRef, Props} 

class A(refToB: ActorRef) extends Actor { ... } 

object A { 
    def props(refToB: ActorRef): Props = Props(new A(refToB)) 
} 

Есть альтернативные способы, вы можете пройти ссылка на актера B на актера A, но использование конструктора, возможно, является самым простым выбором. В приведенном выше примере мы также предоставляем метод для создания правильного Props для актера.

Теперь, когда вы можете контролировать ссылку на актер B, вы можете заменить ссылку на актерский тест тестовым зондом в тестах.

import akka.testkit.TestProbe 

// Initialise a test probe 
val probe = TestProbe() 

// Actor A with reference to actor B replaced with the test probe 
val a = system.actorOf(A.props(probe.ref)) 

// Send a message to actor A 
a ! someMessage 

// Verify that the probe received a correct response from actor A 
p.expectMsgType[MsgToB] 

Обратите внимание, что я создал актер с помощью системы актера из тестового набора вместо использования TestActorRef. Это означает, что обработка сообщения актера будет асинхронной, а не синхронной. Лично я нашел, что асинхронный стиль тестирования лучше подходит, потому что он лучше отражает, как актер запускается в производственной системе. Asynchronous testing is also recommended in the official documentation.

+0

Мне это нравится. Я пошел с оригинальной реализацией, потому что мне нужно было что-то сделать, но это звучит интересно. Цель состоит в том, чтобы протестировать всю актерскую систему от нашего актера входа, который обрабатывает веб-запросы на всю цепочку (обманутых) вызовов службы, которые мы выполняем, и проверяем вывод данных, а также веб-ответ. Одна из проблем заключалась в получении асинхронного поведения, чтобы утверждения не нужно было заказывать. Если это работает, это решает. – Rig