2

テストしているクラスが特定のメソッドを呼び出す可能性がある場合、リフレクションを介して知らせるプロジェクトのテストを作成しようとしています。

以下のコード例に注意してください。

class A implements SomeInterface {
    @Override
    public process(B bInstance) {
        if (Math.rand() < 0.5)
            bInstance.thirdPartyCall(param1, param2); //I need this!
    }
}

このクラスは、process() に渡されたオブジェクトの 1 つからメソッドを呼び出す可能性のあるメソッド process(...) をオーバーライドします。問題のクラスが B() への呼び出しを含むようにコーディングされているかどうか、およびパラメーターが何であるかを調べるために、テストが必要です。呼び出しを文字列としてしか取得できない場合は、それで作業できることを願っています。

A() をオーバーライドするクラスと B() を含むクラスの両方のソース コードがすべてありますが、将来のメンテナンスのためにこれを動的にする必要があります。これは動的にする必要があるため、モックの設定が bInstance からメソッドを呼び出すコードにヒットするかどうかわからないため、モックを作成することはできません。

4

1 に答える 1

4

大まかに言えば、リフレクションはクラスのシグネチャについて教えてくれるので、リフレクションを介してこれを行うことはできませんが、それらの実装については何もわかりません。

目的の処理を実行するには、バイトコードを調べ、各メソッド定義内に表示されるinvokevirtual(または静的メソッドの)コードを調べる必要があります。invokestaticこれを使用して、何が何を呼び出すかを決定する一種の辞書を構築できます。(おそらく、これはIDEが「使用法の検索」機能に依存しているものです。)

自分で定義した「スタンドアロン」メソッドの場合、これで十分な場合があります。ただし、他の場所で定義されたメソッドをオーバーライドまたは実装するメソッドでは、状況が複雑になります。たとえば、独自のRunnable、またはMapサブクラスを定義する場合です。バイトコードを調べるだけでは、メソッド呼び出しの具体的な実装がどうなるかを簡単に知ることはできません(おそらく不可能です)。そのため、呼び出し元が単に参照を持っている場合、マップが呼び出されるかどうかを確実に判断するget()ことはできません。にMap。同様に、Runnable実装がある場合、クラスが直接A呼び出す可能性はほとんどありません。runその呼び出しは、標準ライブラリ内のどこかから来る可能性があります(たとえば、ExecutorServiceまたはからThread.start())、したがって、独自のコードだけでなく、クラスパス上のすべてにわたって非常に大きな推移的な呼び出しマップを作成する必要があります。

さらに、もちろん、最初のポイントに戻すには、リフレクティブコールをまったく検出できません。 Method.invoke()静的分析の観点からは、ほぼすべてを呼び出すことができます。


あなたの意図は良いと思いますが、使用する既存のライブラリが見つからない限り、テスト用にこの種の「カバレッジ」メトリックを開発する価値はありません。

于 2012-08-07T16:10:00.393 に答える