2014-01-22 4 views
10

Я код, который отправляет сообщение на актера, используя его ActorPath не ActorRefДавая ActorPath для testProbe

system.actorSelection("/user/myActor") ! "a message" 

мне нужно, чтобы убедиться, что это сообщение действительно отправлено. Поэтому мне нужно в своих тестах создать testProbe (или что-то подобное), которое живет на этом пути актера, чтобы оно получало это сообщение.

val probe = TestProbe() 
val system.actorOf(probe.ref, "myActor") // ??? I want to give my probe name and path 

ответ

6

Жесткие пути кодирования актер, скорее всего, чтобы сделать вас несчастными позже, почему вы должны принять трудность тестирования это как подсказка дизайна. Я бы рекомендовал использовать ActorRef в качестве первого выбора, и только если это не может быть сделано для работы, вернитесь к ActorPath, но затем держите его гибким, сообщив игроку, какой путь использовать (в сообщении или через конструктор).

+1

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

5

Я выяснил, что вы не элегантное решение.
Я определил помощник актера под названием «ForwardActor»

class ForwardActor(to: ActorRef) extends Actor { 
    def receive = { 
     case x => to.forward(x) 
    } 
} 

то в моем тесте

val probe = TestProbe() 
val system.actorOf(Props(new ForwardActor(probe.ref)), "myActor") 
probe.expectMsg(...) 
+0

Я буду ждать других ответов, чтобы узнать, содержит ли тестовый комплект решение для этой утилиты без такой настройки. – Radian

+0

Это правильный способ сделать это. – sourcedelica

+0

@Roland правильно, большинство людей должны использовать ActorRef, могут быть определенные сценарии, в которых вы хотите, чтобы ActorSelection вместо этого выполнял «огонь и забыл», если вы справляетесь с надежностью на уровне приложения. и в этом случае это решение делает переадресационным актером, из которого вы можете получить ActorPath или ActorSelection. – simbo1905

2

Предположим, что вы хотите проверить этот код:

def f(as: ActorSelection): Unit = as ! "msg" 

Затем вы можете использовать TestProbe с ActorSelection:

val p = TestProbe() 
val as = system.actorSelection(p.ref.path) 
f(as) 
p.expectMsg("msg") 
1

Я разработал небольшую библиотеку/DSL для решения таких случаев (это также позволяет создавать более сложные иерархии и прослушивать сообщения для определенных элементов пути) https://github.com/stanislav-chetvertkov/spy-tree. Вышеуказанный случай может быть рассмотрен следующим образом:

import com.github.spytree.ActorListenersDSL._ 

val myActorProbe = TestProbe() 
("myActor" replyTo myActorProbe.ref).materialize 

context.actorSelection("/user/myActor") ! "a message" 

val response = myActorProbe.expectResponse[String] 
response.message shouldBe "a message" 
Смежные вопросы