12

テストしたいメソッドには、bList の各要素のロジックを含む for ループがあります。

class A {
    void someMethod(){

        for(B b: bList){
            //some logic for b
        }
    }
}

次のテストを実行すると例外が発生します。

@RunWith(MockitoJUnitRunner.class)
class ATest {

    @Mock
    private B b;

    @Mock
    private Map<Int, List<B>> bMap;

    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
    private List<B> bList;

    @Spy
    @InjectMocks
    private C c;
    ....

    @Test
    public void test(){

        //this line executes fine
        when(bList.size()).thenReturn(1);

        //strangely this works fine
        when(bMap.get(any())).thenReturn(bList);

        //ClassCastException
        when(bList.get(0)).thenReturn(b); // or when(bList.get(anyInt())).thenReturn(b);

        c.methodIWantToTest();
    }
}

私が得る例外は次のとおりです。

java.lang.ClassCastException:
org.mockito.internal.creation.jmock.ClassImposterizer$ClassWithSuperclassToWorkAroundCglibBug$$EnhancerByMockitoWithCGLIB$$ cannot be cast to xyz.B

以前にこれに遭遇し、回避策を考え出した人はいますか?

解決策を検索したところ、いくつかのリンクに出くわしました: http://code.google.com/p/mockito/issues/detail?id=251 および http://code.google.com/p/mockito/issues /詳細?id=107

4

2 に答える 2

20

あなたが投稿したこのリンクが示すように、でバグが発生しましたAnswers.RETURNS_DEEP_STUBS

RETURNS_DEEP_STUBSサンプルコードで実際に使用する理由は実際にはありません。Mockito のドキュメントにあるように、「モックがモックを返すたびに妖精が死ぬ」ため、深いスタブが必要かどうかを評価する必要があります。可能であれば、それを取り除くだけで、例が機能します。

ただし、ディープ スタブの使用を主張する場合は、メソッド呼び出しからの戻り値を にアップキャストすることで、このエラーを回避できますObject。たとえば、コード内の問題のある行を次のように置き換えます。

when((Object)bList.get(0)).thenReturn(b);

そうは言っても、私は個人的に@jherricksに同意します。ArrayList最善の解決策は、おそらくモックではなく、モックを含む実際のを使用することListです。唯一の問題は、リストを注入することなので、 を使用する必要があります@Spy。例えば:

@RunWith(MockitoJUnitRunner.class)
class ATest{
  private B b = mock(B.class);
  @Spy
  private List<B> bList = new ArrayList<B>() {{ add(b); }};

  @InjectMocks
  private C c = new C();

  @Test
  public void test(){
    c.methodIWantToTest();
    // verify results
  }
}
于 2012-04-26T03:13:56.560 に答える
0

残念ながら、これは不可能です

ケース: API のテスト:

interface ConfigurationBuilder {...}
configurationBuilder.newServerAction("s1").withName("111")....create();

この使用の主な理由は、コンパイル時の互換性維持です。しかし、mockito は、Java の型消去のため、RETURNS_MOCKS および RETURNS_DEEP_STUBS オプションを使用したチェーン内のジェネリックをサポートできません。

Builder/*<ServerActionBuilder>-erasured generic*/ b = configurationBuilder.newServerAction("s1");
b.withName("111")...create();

上記の例の結果は ServerAction である必要がありますが、mockito では生成されたクラスのオブジェクトです。

問題: ジェネリック型を返すジェネリック メソッドからディープ スタブを返すことができない #484を参照してください。

于 2016-09-14T10:31:30.577 に答える