简体   繁体   English

如何使用 akka BehaviorTestKit 从类型化上下文中测试非类型化参与者部署?

[英]How to test an untyped actor deployment from a typed context using akka BehaviorTestKit?

I'm working on typed akka application and for some reason, I need to use untyped actors from typed context.我正在研究类型化 akka 应用程序,出于某种原因,我需要使用类型化上下文中的非类型化参与者。

I wrote a simple test to try BehaviorTestKit and typed akka testkit.我写了一个简单的测试来尝试 BehaviorTestKit 并输入 akka testkit。 For typed actors it works but for an actor with untyped child I get "only adapted untyped ActorContext permissible " error.对于有类型的演员,它有效,但对于具有无类型孩子的演员,我会收到“仅适用于无类型的 ActorContext 允许”错误。

Here is the parent actor:这是父演员:

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);
    }
}

The child actor童星

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();
    }
}

and the test和测试

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")
    }
  }
}

Exception:例外:

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)
...

The only way I have found is to use untyped akka TestKit instead of BehaviorTestKit.我发现的唯一方法是使用无类型的 akka TestKit 而不是 BehaviorTestKit。 But you also need to store a link to a child somewhere, for instance in a static field (of course it cold be inappropriate in some situations)但是你还需要在某个地方存储一个孩子的链接,例如在一个静态字段中(当然在某些情况下它是不合适的)

    "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))      

    }
  }

I think it is not the best but one of the easiest way.我认为这不是最好的,而是最简单的方法之一。 Another way is to extend actor's protocol and add message with a child inside and ask AppGuardian for the child actor.另一种方法是扩展actor的协议并在里面添加带有子actor的消息并向AppGuardian询问子actor。

I have run into this same error.我遇到了同样的错误。 In the source code I have a typed actor and inside that one I want to spawn a classic actor.在源代码中,我有一个类型化的 actor,在其中我想生成一个经典的 actor。 The child actor is being spawned from a classic system (this system was already in place) Writing the tests I was using the ScalaTestWithActorTestKit because I want to test a typed actor, but then the actor system being used is was typed one, when the source code expects a classic one.子actor是从一个经典系统中产生的(这个系统已经到位)编写测试我使用ScalaTestWithActorTestKit是因为我想测试一个类型化的actor,但是正在使用的actor系统是类型化的,当源代码需要一个经典的。 That's why going back to the classic testKit allows the test to work这就是为什么回到经典的 testKit 允许测试工作

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM