だから私は以前は実際の問題とは関係がありませんでした。答えはまだ当てはまりますが、ディープスタブの答えを使用するモックがモックを返すと、そのような例外が発生します。
それで、本当の問題は何ですか、それはまだジェネリックと型消去によって引き起こされています。次の 2 つの異なるクラスがあります。
テスト:
public class ProcessorTest extends AbstractProcessorTest<Processor, ProcessAlpha>
そして、テストの親:
public abstract class AbstractProcessorTest<P extends AbstractProcessor<T>, T extends AbstractProcess> {
@Mock(answer = ...)
protected P processor;
- そのため、コンパイラは最初に をコンパイルします
AbstractProcessorTest
。そうすると、 P が実際には であることがわかり、AbstractProcessor
この方法でクラスがコンパイルされます。
- 次に、コンパイラはコンパイルし、それが に解決されること
ProcessorTest
を確認しますが、既にコンパイルされているため変更されません。それでも、可能な限り で考慮されるため、そのバイトコードには可能なキャストオペコードが含まれる場合があります。P
Processor
AbstractProcessorTest
P
ProcessorTest
- 実行すると、フィールドに基づいてモックをインスタンス化するように請求された現在の Mockito コードは、で修正したタイプではなく、フィールド
P processor
のタイプを認識します。もちろん、それに応じてモックが作成されます。AbstractProcessor
Processor
ProcessorTest
- メソッドで CCE が発生するの
ProcessorTest.setUp
は、フィールドの一般的な性質により、コンパイラがサイレント キャスト オペコードを確実に導入したためprocessor
です。
また、実際のメソッドを呼び出すようにモックを構成するのは非常に奇妙に見えます。モックは状態で初期化されないため、多くの問題が発生する可能性があります。たぶん、代わりにスパイを使いたいですか?
それが役立つことを願っています。
実際には実際の問題に答えていなかった以前の答え。しかし、Mockito のディープ スタブではまだ役に立つかもしれません
はい、現在リリースされているバージョン (1.9.5) のMockitoは、深いスタブを持つジェネリックをサポートしていません (問題 230 を参照) 。したがって、消去後に既知のタイプであるか、他のタイプであるかに関係なく、優れた境界のみが見つかります。Object
ジェネリックは、ランタイムのものよりもコンパイラのものです。Javaの人々が長い間具体化されたジェネリックを好む理由についてGoogleで検索してください。Neal Gafter は 2006 年に
http://gafter.blogspot.fr/2006/11/reified-generics-for-java.htmlについて書いていますが、他にも興味深い読み物があります。
編集済み vvvvvvvv 2015-01
ただし、コンパイラは特定のケースでジェネリックに関するデータを埋め込みます。このクラス宣言を使用した例では、public class ProcessorTest extends AbstractProcessorTest<Processor, ProcessAlpha>
両方のタイプを読み取ることができます。不格好で遅いリフレクション API を使用します。コードは Mockito コードのマスターに存在し、あなたの例で動作するはずですが、他の問題のためにまだリリースされていません。
Mockito 1.10.x 以降、Mockito はジェネリックをより意識しています。つまり、この宣言のようなモック化された型が型または境界を埋め込んでいる場合はそれらを使用し、メソッドに境界がある場合はそれらを使用します。
つまり、そのようなコードは追加のスタブなしで機能します。つまり、mockito はバイトコードに埋め込まれた境界を検出し、可能であればそれらをモックします (最終的でもプリミティブでもない):
interface UberList<U> extends List<U extends Uber> {
U firstUber();
<D extends Driver> D driver();
}
uberList = mock(UberList.class, RETURNS_DEEP_STUB);
Uber u1 = uberList.iterator().next();
Uber u1 = uberList.firstUber();
Driver d = uberList.driver();
編集しました^^^^^^^^
もちろん、ランタイム宣言はまだ発見できません。たとえばList<Processor> pList;
、Processor
ジェネリック型の場合、 info はerasedになります。コンパイラがコンパイル中に見つけた唯一の利用可能な情報List
。それがどのように行われたかについてあまり詳細を表示しなくても、その型情報はObject
、ジェネリック型情報E
の上限がObject
コンパイラによって解決されるように解決されます (これは暗黙の上限であり、書く必要がないのと同じですextends Object
)。
したがって、それまでの間、必要なタイプにキャストするか、単に深いスタブの回答を使用しないか、冒険好きな場合は、更新された深いスタブの回答を使用してリリースされていないバージョンの Mockito を自分でコンパイルできます。
それが役立つことを願っています。