web-dev-qa-db-ja.com

Mockito:制限されたワイルドカードで型を返すスタブメソッド

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

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()の動作をスタブしようとしている行について文句を言います。バインドされたワイルドカードを使用して型を返すスタブメソッドについてのポインタはありますか?

108
mrmsra

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;
}
29
millhouse

昨日も同じことをしました。 @ nondescript1と@millhouseの両方の回答は、回避策を見つけるのに役立ちました。私のエラーはJava.util.Listではなくcom.google.common.base.Optionalが原因であるため、@ millhouseとほとんど同じコードを使用しましたが、少し汎用性を高めました。したがって、私の小さなヘルパーメソッドでは、List<T>だけでなく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コンパイラが発行するエラーがコンパイラのバグなのか、それともコードが本当に間違っているのかを知っていますか?

14
Marek Radonsky

私は fikovnikのコメント を回答に変えて、最もエレガントなソリューションだと思うので、より可視性を高めていますJava 8+を使用します。

Mockitoのドキュメント は、doReturn()(受け入れられた答えで提案されているように)を最後の手段としてのみ使用することを推奨しています。

代わりに、質問で説明されているコンパイラエラーを回避するには、推奨されるMockito when()アプローチをthenAnswer()およびラムダ(ヘルパーメソッドの代わりに)と共に使用できます。

Mockito.when(mockedClass.mockedMethod()).thenAnswer(x -> resultList)
1
anothernode

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

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

BDDMockito.willReturn(someList).given(dummyClass).dummyMethod();
0
Andreas Siegel