あなたは基本的に、あなたの応答によって変更された私のコメントを回答として再投稿するように私に依頼したので、ここにそれがあります:
次のようにリフレクションを使用してみてください。
when(method.invoke(mock)).thenReturn("Hello world.");
ただし、クラスをモック/スパイできないためMethod
(これは最終的なものです)、これがどのように機能するかはわかりません。Mockitowhen()
は、モックまたはスパイでのみ機能します。これが本当にうまくいっている場合は、もう少し詳細を投稿できますか?
それが機能しない場合は、OP のコメントで提案したように、CGLib ルートに移動して Mockito をバイパスできます。一見するとそれほど難しいものではありません。私の OSS プロジェクトFuncito (モッキング フレームワークではありません) では、Mockito CGLib プロキシ コードの多くを削除し、必要に応じて書き直しました。クラスのプロキシ化とメソッド呼び出しのインターセプトの世界をより簡単に理解できます。
コメント
への追加の返信 これがどのように機能しているかはわかりますが、どのように機能しているかを本当に理解しているかどうかはわかりません。これが問題になる理由は、Mockito 自体の動作方法が今後変更されると、ソリューションが壊れてしまう可能性があるためです。本質的に、それが機能する理由はほとんど偶然ですが、確かに機能します。
動作するはずの方法when()
は、括弧の間で発生するのは、クラスの実際のインスタンスではなく、クラスの単なるファンシープロキシである、以前に作成された Mockito 生成のモックまたはスパイに対するメソッド呼び出しです。プロキシには、偽のプロキシ メソッド呼び出しをインターセプトし、基本的にそれを登録済みのプロキシ メソッド呼び出しのリストに追加する特別なロジックがあります (これはIOngoingStubbing
、後で使用するために、またはそのようなものと呼ばれるものに格納されます)。when()
Java はメソッドを呼び出す前にパラメーターを評価するため、メソッドが実際に実行される前に、プロキシされたメソッド呼び出しが登録/記憶されることが保証されます。がwhen()
行うことは、この IOngoingStubbing から取り出され、thenReturns()
呼び出されるオブジェクトになります。
これを「正しく」使用していませんが、それでも機能します。どのように?IOngoingStubbing
必要なのは、実行前に登録するためにプロキシ上のメソッドを呼び出す必要があることだけwhen()
です。プロキシのメソッドを直接呼び出しているのではなく、プロキシを に渡すことで、プロキシのメソッドを間接的に呼び出していますMethod.invoke()
。したがって、基準が満たされ、when()
すでにプロキシ メソッド呼び出しが に登録されていIOngoingStubbing
ます。
次のコードでも同じような「偶発的な」幸せを見ることができます。
@Test
public void testSomething() throws Exception {
List listMock = mock(List.class);
Method m = List.class.getDeclaredMethod("get", int.class);
m.invoke(listMock, Mockito.anyInt());
when(null).thenReturn("Hello World"); // Huh? passing null?
assertEquals("Hello World", listMock.get(0)); // works!
}
上記のテストは実際にパスします。への引数が null であっても、ステートメントが呼び出されるwhen
前に、プロキシ (つまり、モック) インスタンスに正しいメソッドが呼び出されていることが重要です。when
Mockito が内部での基本的な動作を変更する可能性は低いですが、将来的にこれが壊れる可能性はまだあります。私が言ったように、それが機能することは多かれ少なかれ幸運な偶然です. その仕組みとそれに伴うリスクを理解している限り、より大きな力を発揮できます。