如何通过模拟其中的一个或多个方法来测试Akka Actor功能

ses*_*ses 12 java scala mocking actor akka

我很想知道如何通过在Actor中模拟一些方法(用模拟的替换真实对象/ actor的方法实现)来测试Akka Actor功能.

我用akka.testkit.TestActorRef;

另外:我试图使用,SpyingProducer但目前尚不清楚如何使用它.(就像我,如果我在其实现中创建了actor,它将与我现在一样).谷歌搜索结果不是很详细.

我用powemockitojava.但是这没关系.我很想知道how to do it in principle 任何语言与任何框架

(所以如果你不知道power/mockito如何工作只是提供你的代码..(请)或完全了解你将如何使用你知道的工具.)

所以,假设我们有一个要测试的Actor:

package example.formock;

import akka.actor.UntypedActor;

public class ToBeTestedActor extends UntypedActor {

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

        if (message instanceof String) {
            getSender().tell( getHelloMessage((String) message), getSelf());
        }

    }

    String getHelloMessage(String initMessage) { // this was created for test purposes (for testing mocking/spy capabilities). Look at the test
        return "Hello, " + initMessage;
    }

}
Run Code Online (Sandbox Code Playgroud)

在我们的测试中,我们想要替换getHelloMessage()其他东西.

这是我的尝试:

package example.formock;

import akka.testkit.TestActorRef;
...

@RunWith(PowerMockRunner.class)
@PrepareForTest(ToBeTestedActor.class)
public class ToBeTestedActorTest {

    static final Timeout timeout = new Timeout(Duration.create(5, "seconds"));

    @Test
    public void getHelloMessage() {

        final ActorSystem system = ActorSystem.create("system");

        // given
        final TestActorRef<ToBeTestedActor> actorRef = TestActorRef.create(
                system,
                Props.create(ToBeTestedActor.class),
                "toBeTestedActor");

        // First try:
        ToBeTestedActor actorSpy = PowerMockito.spy(actorRef.underlyingActor());
        // change functionality
        PowerMockito.when(actorSpy.getHelloMessage (anyString())).thenReturn("nothing"); // <- expecting result   


        try {

           // when
           Future<Object> future = Patterns.ask(actorRef, "Bob", timeout);
           // then
           assertTrue(future.isCompleted());

            // when
           String resultMessage = (String) Await.result(future, Duration.Zero());
            // then
           assertEquals("nothing", resultMessage);  // FAIL HERE

        } catch (Exception e) {
           fail("ops");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

结果:

org.junit.ComparisonFailure: 
Expected :nothing
Actual   :Hello, Bob
Run Code Online (Sandbox Code Playgroud)

小智 10

Akka有一个类AutoPilot,它基本上是演员的一般模拟,具有响应消息和断言消息被发送的能力. http://doc.akka.io/docs/akka/snapshot/java/testing.html

这是该页面的java示例.您可以创建一个探测器,设置一个可以响应消息的自动驾驶仪,并从中获取一个ActorRef可以代替您真实演员的消息.

new JavaTestKit(system) {{
  final JavaTestKit probe = new JavaTestKit(system);
  // install auto-pilot
  probe.setAutoPilot(new TestActor.AutoPilot() {
    public AutoPilot run(ActorRef sender, Object msg) {
      sender.tell(msg, ActorRef.noSender());
      return noAutoPilot();
    }
  });
  // first one is replied to directly ...
  probe.getRef().tell("hello", getRef());
  expectMsgEquals("hello");
  // ... but then the auto-pilot switched itself off
  probe.getRef().tell("world", getRef());
  expectNoMsg();
}};
Run Code Online (Sandbox Code Playgroud)


Jas*_*onG 1

所以我可能不理解这个问题,但你可能不想嘲笑演员,因为嘲笑的目的是用具有调用期望的测试副本替换诸如 dao 之类的东西 - actor 并不真正符合要求因为它是您扩展的东西而不是依赖项 - 模拟实际上只适用于真正的依赖项。

TestActorRef 专门为您提供了对底层 Actor 的访问 - 在大多数正常情况下,您只能向 Actor 发送消息,而不能直接调用其上的任何内容。TestActoRef 通过允许您访问您真正的 Actor 扩展而不仅仅是您只能访问的 ActorRef 来消除此限制!或者 ?反对(发送或询问)。

我是一名 Scala 开发人员,所以我的见解希望是不可知的。我具体不知道java api,但这应该不重要。

我的建议是通过 actor ref 获取真实的 Actor 对象,然后测试该方法或找出某种方法通过真实消息获取测试覆盖率。