Как проверить развертывание нетипизированного субъекта из типизированного контекста, используя akka BehaviorTestKit? - PullRequest
0 голосов
/ 11 февраля 2019

Я работаю над типизированным приложением akka и по какой-то причине мне нужно использовать нетипизированные актеры из типизированного контекста.

Я написал простой тест, чтобы попробовать BehaviorTestKit, и набрал akka testkit.Для типизированных актеров это работает, но для актера с нетипизированным ребенком я получаю "только адаптированный нетипизированный допустимый " ActorContext.

Вот родительский актер:

public class AppGuardianTest extends AbstractBehavior<String> {
    private ActorContext context;

    public AppGuardianTest(ActorContext context) {
        this.context = context;

        ActorRef child = Adapter.actorOf(context, SomeUntypedActor.props(), "child");     
    }
    @Override
    public Receive<String> createReceive() {
        return receiveBuilder()
                .onMessage(String.class, m -> Behaviors.same())
                .onSignal(PostStop.class, signal -> postStop()).build();
    }
    private Behavior<String> postStop() {
        context.getLog().info("Application stopped");
        return this;
    }
    public static Behavior behavior() {
        return Behaviors.setup(AppGuardianTest::new);
    }
}

Ребенок актер

public class SomeUntypedActor extends AbstractActor {
    public static Props props() {
        return Props.create(SomeUntypedActor.class);
    }

    @Override
    public Receive createReceive() {
        return receiveBuilder().matchAny(m -> {
            System.out.println(m);
        }).build();
    }
}

и тест

import akka.actor.testkit.typed.scaladsl.{BehaviorTestKit, ScalaTestWithActorTestKit}
import some.test.AppGuardianTest
import org.scalatest.WordSpecLike
class AppGuardianSpec extends ScalaTestWithActorTestKit with WordSpecLike {

  "appGuardian" should {
    "deploy child" in {
      val testKit = BehaviorTestKit(AppGuardianTest.behavior())
      val child = testKit.childInbox[String]("child")
    }
  }
}

Исключение:

only adapted untyped ActorContext permissible (Inbox(Actor[akka.actor.typed.inbox://anonymous/testkit#1338528633]) of class akka.actor.testkit.typed.internal.EffectfulActorContext)
java.lang.UnsupportedOperationException: only adapted untyped ActorContext permissible (Inbox(Actor[akka.actor.typed.inbox://anonymous/testkit#1338528633]) of class akka.actor.testkit.typed.internal.EffectfulActorContext)
    at akka.actor.typed.internal.adapter.ActorContextAdapter$.toUntypedImp(ActorContextAdapter.scala:110)
    at akka.actor.typed.internal.adapter.ActorContextAdapter$.toUntyped(ActorContextAdapter.scala:125)
    at akka.actor.typed.javadsl.Adapter$.actorOf(Adapter.scala:88)
    at akka.actor.typed.javadsl.Adapter.actorOf(Adapter.scala)
    at some.test.AppGuardianTest.<init>(AppGuardianTest.java:15)
    at akka.actor.typed.javadsl.Behaviors$.$anonfun$setup$1(Behaviors.scala:43)
    at akka.actor.typed.Behavior$DeferredBehavior$$anon$1.apply(Behavior.scala:239)
    at akka.actor.typed.Behavior$.start(Behavior.scala:324)
...

1 Ответ

0 голосов
/ 08 апреля 2019

Единственный способ, который я нашел, - это использовать нетипизированный akka TestKit вместо BehaviorTestKit.Но вам также нужно где-то хранить ссылку на ребенка, например, в статическом поле (конечно, в некоторых ситуациях это может быть неприемлемо)

    "appGuardian" should {
    "deploy child" in {
      val AppG = Adapter.spawn(system, AppGuardianTest.behavior(), "app_g")

      val actor = Await.result(Future {
        while (AppGuardianTest.child == null) {
          Thread.sleep(100)
        }
        AppGuardianTest.child
      }(ExecutionContext.global), new FiniteDuration(5, TimeUnit.SECONDS))      

    }
  }

Я думаю, что это не лучший, но один изСамый простой способ.Другой способ - расширить протокол актера и добавить сообщение с дочерним элементом внутри и попросить AppGuardian для дочернего актера.

...