Mockito ClassCastException

20,438

As this link you posted indicates, you've encountered a bug with Answers.RETURNS_DEEP_STUBS.

I don't actually see any reason to actually use RETURNS_DEEP_STUBS in your example code. You really should try to evaluate whether or not you need deep stubs, because, as the Mockito docs say, "every time a mock returns a mock a fairy dies." So if you can, just take that out and your example will work.

However, if you insist on using deep stubs, you can hack around this error by up-casting the return value from the method call to Object. For example, replace the offending line in your code with this:

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

All that being said, I personally agree with @jhericks. The best solution is probably to use an actual ArrayList which contains your mock as opposed to mocking List. The only problem is getting your list injected, so you'd have to use @Spy. For example:

@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
  }
}
Share:
20,438
aces.
Author by

aces.

Updated on July 05, 2022

Comments

  • aces.
    aces. almost 2 years

    The method I want to test has a for loop with logic for each element in bList:

    class A {
        void someMethod(){
    
            for(B b: bList){
                //some logic for b
            }
        }
    }
    

    I get an exception when executing following test:

    @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();
        }
    }
    

    The exception I get is:

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

    Has anyone encountered this before and come up with a workaround?

    I have searched for a solution and have come across some links: http://code.google.com/p/mockito/issues/detail?id=251 and http://code.google.com/p/mockito/issues/detail?id=107