3

私は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には、次のいずれかを行います。

  1. パッケージプライベートにするために必要
  2. または、アクターのパブリック インターフェースをテストします。つまり、次のアクターLogWriterが私のアクターから正しく解析されたメッセージを受信したことを確認します。LogRowParser

私の質問:

  1. オプション#1に欠点はありますか?アクターがメッセージのみを介して通信すると仮定すると、カプセル化とクリーンなオープン インターフェイスはそれほど重要ではありませんか?
  2. オプション #2 を使用しようとした場合、アクターから送信されたメッセージをテスト ダウンストリーム (テストLogRowParserとキャッチLogWriter) でキャッチする方法はありますか? さまざまな例を確認しましJavaTestKitたが、それらはすべて、送信者への応答であるメッセージをキャッチしており、新しいアクターに送信されたメッセージを傍受する方法を示すものはありません.
  3. 私が見逃している別のオプションはありますか?

ありがとう!

UPD:次 のようなオプションも検討したことを忘れていました。

  • ロジックをアクターからヘルパー クラスに完全に移動します。akkaではよくあることですか?
  • Powermock...しかし、再設計が可能であれば回避しようとしています
4

2 に答える 2

2

そのメソッドをプライベートにする正当な理由は本当にありません。一般に、クラスのインスタンスを直接参照している誰かがそのメソッドを呼び出せないようにするために、クラスのメソッドをプライベートにします。アクター インスタンスでは、誰もそのアクター クラスのインスタンスを直接参照できません。そのアクター クラスのインスタンスと通信できるのは、メールボックス経由ActorRefで処理されるメッセージを送信することによってのみ通信できる軽量プロキシである だけですonReceive。アンActorRefそのアクター クラスの内部状態またはメソッドを公開しません。これは、アクター システムの大きなセールス ポイントの 1 つです。アクター インスタンスは、その内部状態とメソッドを完全にカプセル化し、それらを外部から保護し、メッセージの受信に応じて内部のもののみを変更できるようにします。そのため、そのメソッドをプライベートとしてマークする必要はないようです。

編集

アクター (IMO) の単体テストは、常にreceive機能を実行する必要があります。の処理によって呼び出される内部メソッドがある場合は、receiveこれらのメソッドを個別にテストすることに集中するのではなく、テスト シナリオ中に渡すメッセージを介して、それらの呼び出しにつながるパスが適切に実行されることを確認してください。

あなたの特定の例では、子アクターに送信されるメッセージをparse生成しています。私にとって、それが期待どおりに機能することを知っているということは、 が正しいメッセージを受信したと断言することを意味します。これを行うには、子の作成をオーバーライドできるようにし、テスト コードでそれを行い、アクターの作成を. 次に、そのプローブで を使用して、期待されるメッセージを受信したことを確認し、 の機能もテストできます。ParsedLoglogWriterparselogWriterlogWriterTestProbeexpectMsgParsedLogparse

アクターの実際のビジネスを別のよりテスト可能なクラスに移動し、それをアクターから呼び出すという他のコメントに関する限り、これを行う人もいるので、前代未聞ではありません。私は個人的にはしませんが、それは私だけです。そのアプローチがうまくいくなら、大きな問題はないと思います。

于 2015-04-02T11:15:11.800 に答える