私はakkaが初めてで、Javaでakkaを試しています。アクター内のビジネス ロジックの単体テストについて理解したいと思います。ドキュメントを読みましたが、アクター内の分離されたビジネス ロジックの唯一の例は次のとおりです。
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());
}
これは単純ですが、テストしたいメソッドが公開されていることを意味します。ただし、アクターはメッセージを介してのみ通信する必要があることを考えると、パブリック メソッドを使用する理由はないと理解したので、メソッドをプライベートにしました。以下の例のように:
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
には、次のいずれかを行います。
- パッケージプライベートにするために必要
- または、アクターのパブリック インターフェースをテストします。つまり、次のアクター
LogWriter
が私のアクターから正しく解析されたメッセージを受信したことを確認します。LogRowParser
私の質問:
- オプション#1に欠点はありますか?アクターがメッセージのみを介して通信すると仮定すると、カプセル化とクリーンなオープン インターフェイスはそれほど重要ではありませんか?
- オプション #2 を使用しようとした場合、アクターから送信されたメッセージをテスト ダウンストリーム (テスト
LogRowParser
とキャッチLogWriter
) でキャッチする方法はありますか? さまざまな例を確認しましJavaTestKit
たが、それらはすべて、送信者への応答であるメッセージをキャッチしており、新しいアクターに送信されたメッセージを傍受する方法を示すものはありません. - 私が見逃している別のオプションはありますか?
ありがとう!
UPD:次 のようなオプションも検討したことを忘れていました。
- ロジックをアクターからヘルパー クラスに完全に移動します。akkaではよくあることですか?
- Powermock...しかし、再設計が可能であれば回避しようとしています