148

次のコードを検討してください。

public class DummyClass {
    public List<? extends Number> dummyMethod() {
        return new ArrayList<Integer>();
    }
}
public class DummyClassTest {
    public void testMockitoWithGenerics() {
        DummyClass dummyClass = Mockito.mock(DummyClass.class);
        List<? extends Number> someList = new ArrayList<Integer>();
        Mockito.when(dummyClass.dummyMethod()).thenReturn(someList); //Compiler complains about this
    }
}

コンパイラは、 の動作をスタブしようとしている行について不平を言いdummyMethod()ます。バインドされたワイルドカードを持つ型を返すメソッドをスタブ化する方法についての指針はありますか?

4

5 に答える 5

211

この目的のために、型安全でないメソッドdoReturnを使用することもできます。

@Test
public void testMockitoWithGenerics()
{
    DummyClass dummyClass = Mockito.mock(DummyClass.class);
    List<? extends Number> someList = new ArrayList<Integer>();

    Mockito.doReturn(someList).when(dummyClass).dummyMethod();

    Assert.assertEquals(someList, dummyClass.dummyMethod());
}

Mockito の Google グループで 議論されているように。

これは より単純ですがthenAnswer、タイプ セーフではないことに注意してください。型の安全性が気になる場合は、ミルハウスの答えが正しいです。

追加の詳細

明確にするために、観察されたコンパイラエラーは次のとおりです。

The method thenReturn(List<capture#1-of ? extends Number>) in the type OngoingStubbing<List<capture#1-of ? extends Number>> is not applicable for the arguments (List<capture#2-of ? extends Number>)

呼び出し中にコンパイラが最初のワイルドカード タイプを割り当てた後、呼び出しの 2 番目のワイルドカード タイプが同じ whenであることを確認できないと思います。thenReturn

キャプチャする必要がある非ワイルドカード タイプを受け取りthenAnswerながら、ワイルドカード タイプを受け入れるため、この問題には遭遇しないようです。thenReturnMockito のOngoingStubbingから、

OngoingStubbing<T> thenAnswer(Answer<?> answer);
OngoingStubbing<T> thenReturn(T value);
于 2012-05-21T15:52:44.273 に答える
34

someListいくつかの既知の値をロードできるようにしたいと考えています。Answer<T>テンプレート化されたヘルパー メソッドと一緒に使用して、すべてをタイプ セーフに保つアプローチを次に示します。

@Test
public void testMockitoWithGenericsUsingAnswer()
{
    DummyClass dummyClass =  Mockito.mock(DummyClass.class);

    Answer<List<Integer>> answer = setupDummyListAnswer(77, 88, 99);
    Mockito.when(dummyClass.dummyMethod()).thenAnswer(answer);

    ...
}

private <N extends Number> Answer<List<N>> setupDummyListAnswer(N... values) {
    final List<N> someList = new ArrayList<N>();

    someList.addAll(Arrays.asList(values));

    Answer<List<N>> answer = new Answer<List<N>>() {
        public List<N> answer(InvocationOnMock invocation) throws Throwable {
            return someList;
        }   
    };
    return answer;
}
于 2011-10-05T01:01:31.487 に答える
19

昨日も同じものをぶつけました。@nondescript1 と @millhouse からの両方の回答は、回避策を見つけるのに役立ちました。@millhouse とほぼ同じコードを使用しましたが、エラーの原因はjava.util.Listではなくcom.google.common.base.Optional. Tしたがって、私の小さなヘルパー メソッドでは、次だけでなく、任意の型を使用できますList<T>

public static <T> Answer<T> createAnswer(final T value) {
    Answer<T> dummy = new Answer<T>() {
        @Override
        public T answer(InvocationOnMock invocation) throws Throwable {
            return value;
        }
    };
    return dummy;
}

このヘルパー メソッドを使用すると、次のように記述できます。

Mockito.when(dummyClass.dummyMethod()).thenAnswer(createAnswer(someList));

thenReturn(...)これは問題なくコンパイルされ、メソッドと同じことを行います。

Javaコンパイラが発行するエラーがコンパイラのバグなのか、それともコードが本当に間違っているのか、誰かが知っていますか?

于 2013-07-25T19:41:26.697 に答える
0

Marek Radonsky によって提案されたユーティリティ メソッドは機能しますが、fikovnik が提案した (IMHO 奇妙に見える) ラムダ式を必要としない別のオプションもあります。

同様の質問に対するこの回答が示すように、次のものも使用できます。

BDDMockito.willReturn(someList).given(dummyClass).dummyMethod();
于 2016-07-13T11:49:35.517 に答える