首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >阿卡。如何在java中模拟儿童角色?

阿卡。如何在java中模拟儿童角色?
EN

Stack Overflow用户
提问于 2016-03-13 23:59:08
回答 3查看 1.3K关注 0票数 5

假设我有一个家长演员,他自己创建了actor。

代码语言:javascript
复制
public static class Parent extends UntypedActor {

private ActorRef child = context().actorOf(Props.create(Child.class));

    @Override
    public void onReceive(Object message) throws Exception {
        // do some stuff
        child.tell("some stuff", self());
    }
}

public static class Child extends UntypedActor {

    @Override
    public void onReceive(Object message) throws Exception {

    }
}

我怎么能嘲笑这个儿童演员呢?谷歌没有给我任何合理的结果。Akka的文档告诉我,创建一个演员是一个很好的实践。但是,如果我甚至不能测试我的演员,我怎么能遵循这种做法呢?

EN

回答 3

Stack Overflow用户

发布于 2016-03-14 16:17:01

我使用这个答案中描述的探测器来回答一个类似的问题:

How to mock child Actors for testing an Akka system?

代码语言:javascript
复制
ActorSystem system = ActorSystem.create();

new JavaTestKit( system )
{{
  final JavaTestKit probe = new JavaTestKit( system );
  final Props props = Props.create( SupervisorActor.class );

  final TestActorRef<SupervisorActor> supervisorActor =
    TestActorRef.create( system, props, "Superman" );

  supervisorActor.tell( callCommand, getTestActor() );

  probe.expectMsgEquals(42);
  assertEquals(getRef(), probe.getLastSender());
}};
票数 1
EN

Stack Overflow用户

发布于 2016-03-14 17:43:20

下面的代码将用Scala编写,但我想这也应该适用于Java。答案是,您可以使用TestProbe来模拟您的孩子演员。让我们举个例子:

代码语言:javascript
复制
import akka.actor.{Actor, Props}

class Parent extends Actor {
  import Parent._

  val child = context.actorOf(Child.props)

  override def receive: Receive = {
    case TellName(name) => child ! name
    case Reply(msg) => sender() ! msg
  }
}

object Parent {
  case class TellName(name: String)
  case class Reply(text: String)
  def props = Props(new Parent)
}

class Child extends Actor {
  override def receive: Actor.Receive = {
    case name: String => sender !  Parent.Reply(s"Hi there $name")
  }
}

object Child {
  def props = Props(new Child)
}

因此,我们有一个Parent执行元,它向Child执行元发送消息TellName。在接收到消息后,Child参与者将通过向其发送者发送带有内容的Reply消息来响应。“嗨,乔”。现在,这是一个测试:

代码语言:javascript
复制
class ParentSpec extends TestKit(ActorSystem("test")) with WordSpecLike with Matchers with ImplicitSender {


  val childProbe = TestProbe()

  "Parent actor" should {
    "send a message to child actor" in {
      childProbe.setAutoPilot(new AutoPilot {
        override def run(sender: ActorRef, msg: Any): AutoPilot = msg match {
          case name: String => sender ! Reply(s"Hey there $name")
            NoAutoPilot
        }
      })
      val parent = system.actorOf(Props(new Parent {
        override val child = childProbe.ref
      }))
      parent ! TellName("Johnny")
      childProbe.expectMsg("Johnny") // Message received by a test probe
      expectMsg("Hey there Johnny") // Reply message
    }
  }
}

现在,为了模拟我们的Child参与者的行为,我们可以使用setAutoPilot方法来定义它在收到特定类型的消息后如何回复。在我们的示例中,假设Child actor接收到字符串类型的消息"Jonny",它将以内容为“嘿there”的Reply消息作为响应。首先,我们发送内容为"Johnny“的TellName。然后我们可以断言我们的模拟角色收到了什么消息- childProbe.expectMsg("Johnny")。之后,我们可以断言reply message - expectMsg("Hey there Johnny")。请注意,回复消息将是“你好,约翰尼”,而不是“你好,约翰尼”,这对应于我们在mocked Child actor中定义的更改的行为。

票数 0
EN

Stack Overflow用户

发布于 2018-10-11 03:34:17

有一些several approaches你可以用来模拟儿童演员。其中之一是从父actor外部化用于创建子对象的代码。

为此,您需要重写您的父actor,并向其传递一个将创建您的子actor的函数:

注意:由于UntypedActor的原因,我们将使用AbstractActor而不是deprecation in version 2.5.0

代码语言:javascript
复制
public class Parent extends AbstractActor {

  private final ActorRef child;

  public Parent(Function<ActorRefFactory, ActorRef> childCreator) {
    this.child = childCreator.apply(getContext());
  }

  public static Props props(Function<ActorRefFactory, ActorRef> childCreator) {
    return Props.create(Parent.class, childCreator);
  }

  @Override
  public Receive createReceive() {
    return receiveBuilder()
        .matchEquals("send ping", s -> child.tell("ping", getSelf()))
        .match(String.class, System.out::println)
        .build();
  }
}

你的孩子演员将保持不变:

代码语言:javascript
复制
public class Child extends AbstractActor {

  @Override
  public Receive createReceive() {
    return receiveBuilder()
        .matchEquals("ping", s -> getSender().tell("pong", getSelf()))
        .build();
  }
}

现在,在您的测试中,您可以使用probe actor reference来测试应该发送给Child actor的消息,即probe将充当Child actor mock:

代码语言:javascript
复制
public class ParentTest {

  static ActorSystem system;

  @BeforeClass
  public static void setUpClass() {
    system = ActorSystem.create();
  }

  @AfterClass
  public static void tearDownClass() {
    TestKit.shutdownActorSystem(system);
    system = null;
  }

  @Test
  public void givenParent_whenSendPing_thenPingChild() {
    TestKit probe = new TestKit(system);

    Function<ActorRefFactory, ActorRef> childCreator = arf -> probe.getRef();

    ActorRef parentActor = system.actorOf(Parent.props(childCreator));

    probe.send(parentActor, "send ping");

    probe.expectMsgEquals("ping");
  }
}

因此,不要使用(将在实际应用程序代码中使用):

代码语言:javascript
复制
Function<ActorRefFactory, ActorRef> childCreator = arf -> arf
                                      .actorOf(Props.create(Child.class));

我们将使用:

代码语言:javascript
复制
Function<ActorRefFactory, ActorRef> childCreator = arf -> probe.getRef();

并检查probe是否接收到"ping“消息。

希望能有所帮助。有关给定方法的更多信息,请访问here

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35972430

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档