假设我有一个家长演员,他自己创建了actor。
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的文档告诉我,创建一个演员是一个很好的实践。但是,如果我甚至不能测试我的演员,我怎么能遵循这种做法呢?
发布于 2016-03-14 16:17:01
我使用这个答案中描述的探测器来回答一个类似的问题:
How to mock child Actors for testing an Akka system?
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());
}};
发布于 2016-03-14 17:43:20
下面的代码将用Scala编写,但我想这也应该适用于Java。答案是,您可以使用TestProbe来模拟您的孩子演员。让我们举个例子:
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
消息来响应。“嗨,乔”。现在,这是一个测试:
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中定义的更改的行为。
发布于 2018-10-11 03:34:17
有一些several approaches你可以用来模拟儿童演员。其中之一是从父actor外部化用于创建子对象的代码。
为此,您需要重写您的父actor,并向其传递一个将创建您的子actor的函数:
注意:由于UntypedActor
的原因,我们将使用AbstractActor
而不是deprecation in version 2.5.0。
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();
}
}
你的孩子演员将保持不变:
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:
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");
}
}
因此,不要使用(将在实际应用程序代码中使用):
Function<ActorRefFactory, ActorRef> childCreator = arf -> arf
.actorOf(Props.create(Child.class));
我们将使用:
Function<ActorRefFactory, ActorRef> childCreator = arf -> probe.getRef();
并检查probe
是否接收到"ping“消息。
希望能有所帮助。有关给定方法的更多信息,请访问here。
https://stackoverflow.com/questions/35972430
复制相似问题