私のテストでは、次の行があります:
_when(client.runTask(anyString(), anyString(), isA(Iterable.class)).thenReturn(...)
_
isA(Iterable.class)
は、_Iterable<Integer>
_に準拠するためにチェックされていない変換が必要であるという警告を生成します。そのための構文は何ですか?
_isA(Iterable<Integer>.class)
isA((Iterable<Integer>)Iterable.class
_
動作しない。
助言がありますか?
はい、これはMockito/Hamcrestの一般的な問題です。一般的に、ジェネリッククラスでisA()
を使用すると警告が発生します。
最も一般的なジェネリッククラスには、定義済みのMockitoマッチャーがあります: anyList() 、anyMap()
、anySet()
およびanyCollection()
。
提案:
Mockito 2.1.0では、Iterableを照合するための新しい anyIterable() メソッドが追加されました。
when(client.runTask(anyString(), anyString(), anyIterable()).thenReturn(...)
Eclipseの警告を取り除きたいだけの場合。オプションは Eclipse Indigo 以降に存在します:
ウィンドウ>設定> Java>コンパイラ>エラー/警告>ジェネリック型>不可避のジェネリック型の問題を無視
問題が1回だけ発生する場合は、これを行うことをお勧めします。個人的にはisA(Iterable.class)
が必要だったことを覚えていません。
Daniel Prydenが言うように、@SuppressWarnings
をローカル変数またはヘルパーメソッドに制限できます。
これは問題を完全に解決します。ただし、次の2つの欠点があります。
TypeToken
クラスを提供するライブラリへの追加の依存関係があります。ここでは GuavaのTypeTokenクラス を使用しました。 GsonにはTypeToken
クラス、JAX-RSにはGenericType
もあります。汎用マッチャーを使用する:
import static com.arendvr.matchers.InstanceOfGeneric.isA;
import static org.mockito.ArgumentMatchers.argThat;
// ...
when(client.runTask(anyString(), anyString(), argThat(isA(new TypeToken<Iterable<Integer>>() {}))))
.thenReturn(...);
ジェネリックマッチャークラス:
package com.arendvr.matchers;
import com.google.common.reflect.TypeToken;
import org.mockito.ArgumentMatcher;
public class InstanceOfGeneric<T> implements ArgumentMatcher<T> {
private final TypeToken<T> typeToken;
private InstanceOfGeneric(TypeToken<T> typeToken) {
this.typeToken = typeToken;
}
public static <T> InstanceOfGeneric<T> isA(TypeToken<T> typeToken) {
return new InstanceOfGeneric<>(typeToken);
}
@Override
public boolean matches(Object item) {
return item != null && typeToken.getRawType().isAssignableFrom(item.getClass());
}
}
これが私がすることです:
// Cast from Class<Iterable> to Class<Iterable<Integer>> via the raw type.
// This is provably safe due to erasure, but will generate an unchecked warning
// nonetheless, which we suppress.
@SuppressWarnings("unchecked")
Class<Iterable<Integer>> klass
= (Class<Iterable<Integer>>) (Class) Iterable.class;
// later
isA(klass) // <- now this is typesafe
ステートメントの上に@SuppressWarnings("unchecked")
を追加できます。他に方法はありませんが、気になる場合は、キャストをヘルパーメソッドに移動できます。
これを行う方法はありません。簡単にするために、警告なしにこの変数を初期化することはできません:
Class<Iterable<Integer>> iterableIntegerClass = ?
解決策の1つは、 pseudo-typedef antipattern 、を使用することです。IntegerIterable
インターフェイスを作成して使用します
interface IntegerIterable extends Iterable<Integer> {}
その後
isA(IntegerIterable.class)
警告を生成しなくなります。ただし、Iterable
を実装するクラスを拡張して、IntegerIterable
を実装できるようにする必要があります。例:
public class IntegerArrayList extends ArrayList<Integer> implements IntegerIterable {}
うーんおいしい...
だから、私はあなたの方法に追加することにより、亀裂を紙で覆うことを検討することをお勧めします:
@SuppressWarnings("unchecked")