gpt4 book ai didi

java - 在 Akka 中对私有(private)方法进行单元测试

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:44:22 26 4
gpt4 key购买 nike

我是 akka 的新手,我正在 java 上尝试 akka。我想了解 Actor 内业务逻辑的单元测试。我读了documentation actor 中孤立业务逻辑的唯一示例是:

static class MyActor extends UntypedActor {
public void onReceive(Object o) throws Exception {
if (o.equals("say42")) {
getSender().tell(42, getSelf());
} else if (o instanceof Exception) {
throw (Exception) o;
}
}
public boolean testMe() { return true; }
}

@Test
public void demonstrateTestActorRef() {
final Props props = Props.create(MyActor.class);
final TestActorRef<MyActor> ref = TestActorRef.create(system, props, "testA");
final MyActor actor = ref.underlyingActor();
assertTrue(actor.testMe());
}

虽然这很简单,但它意味着我要测试的方法是公开的。然而,考虑到 Actor 应该只通过消息进行交流,我的理解是没有理由拥有公共(public)方法,所以我将我的方法设为私有(private)。就像下面的例子:

public class LogRowParser extends AbstractActor {
private final Logger logger = LoggerFactory.getLogger(LogRowParser.class);

public LogRowParser() {
receive(ReceiveBuilder.
match(LogRow.class, lr -> {
ParsedLog log = parse(lr.rowText);
final ActorRef logWriter = getContext().actorOf(Props.create(LogWriter.class));
logWriter.tell(log, self());
}).
matchAny(o -> logger.info("Unknown message")).build()
);
}

private ParsedLog parse(String rowText) {
// Log parsing logic
}
}

所以要测试方法 parse 我要么:

  1. 需要它来使包私有(private)
  2. 或者测试 actor 的公共(public)接口(interface),即下一个 actor LogWriter 从我的 actor LogRowParser 接收到正确的解析消息

我的问题:

  1. 选项 1 有什么缺点吗?假设参与者仅通过消息进行通信,那么封装和干净的开放接口(interface)就不那么重要了?
  2. 如果我尝试使用选项 #2,是否有办法在下游测试中捕获从 actor 发送的消息(测试 LogRowParser 并在 LogWriter 中捕获)?我查看了有关 JavaTestKit 的各种示例,但所有示例都在捕获作为对发件人的响应的消息,而没有显示如何拦截发送给新参与者的消息。
  3. 我还缺少其他选项吗?

谢谢!

更新:忘了说我也考虑过以下选项:

  • 将逻辑从 actor 中完全转移到辅助类中。这是 akka 的常见做法吗?
  • Powermock...但如果可以重新设计,我会尽量避免使用它

最佳答案

确实没有充分的理由将该方法设为私有(private)。人们通常将类的方法设为私有(private),以防止直接引用该类实例的人调用该方法。对于 actor 实例,没有人会直接引用该 actor 类的实例。您可以与该 actor 类的实例进行通信的是一个 ActorRef,它是一个轻量级代理,只允许您通过发送由 onReceive 处理的消息进行通信通过邮箱。 ActorRef 不公开该 actor 类的任何内部状态或方法。这是 Actor 系统的一大卖点。一个 actor 实例完全封装了它的内部状态和方法,保护它们不受外界影响,并且只允许这些内部事物响应接收消息而改变。这就是为什么似乎没有必要将该方法标记为私有(private)的原因。

编辑

参与者的单元测试,IMO,应该始终通过receive 功能。如果您有一些内部方法随后由 receive 中的处理程序调用,则您不应专注于孤立地测试这些方法,而应确保通过您在测试场景中传递的消息。

在您的特定示例中,parse 正在生成一条 ParsedLog 消息,然后将该消息发送到 logWriter 子 actor。对我来说,知道 parse 按预期工作意味着断言 logWriter 收到了正确的消息。为此,我将允许重写子 logWriter 的创建,然后在测试代码中执行此操作,并用 TestProbe 替换 actor 创建。然后,您可以对该探测器使用 expectMsg 以确保它收到预期的 ParsedLog 消息,从而也测试 parse 中的功能。

就您关于将 actor 的实际业务转移到一个单独且更可测试的类然后从 actor 中调用它的其他评论而言,有些人这样做,所以这并非闻所未闻。我个人不喜欢,但这就是我。如果这种方法适合您,我认为它没有任何重大问题。

关于java - 在 Akka 中对私有(private)方法进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29401503/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com