Предоставление ActorPath для testProbe

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

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

4 ответа

Решение

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

Я понял не элегантное решение.
Я определил вспомогательный актор под названием "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(...)

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

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

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

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

Я разработал небольшую библиотеку /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"
Другие вопросы по тегам