我想测试的方法有一个for循环,其中包含bList中每个元素的逻辑:
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/detail?id=107
答案 0 :(得分:19)
如this link you posted所示,您遇到了Answers.RETURNS_DEEP_STUBS
的错误。
我实际上没有看到在示例代码中实际使用RETURNS_DEEP_STUBS
的任何理由。你真的应该尝试评估你是否需要深层存根,因为,Mockito docs say,“每当一个模拟器返回一个模拟器,一个仙女死了。”所以,如果可以,那就把它拿出来,你的例子就可以了。
但是,如果您坚持使用深层存根,则可以通过将方法调用的返回值向上转换为Object
来解决此错误。例如,用以下代码替换代码中的违规行:
when((Object)bList.get(0)).thenReturn(b);
所有这一切,我个人都同意@jhericks。最好的解决方案可能是使用包含模拟的实际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
}
}
答案 1 :(得分:0)
不幸的是,这是不可能的
案例:API测试:
interface ConfigurationBuilder {...}
configurationBuilder.newServerAction("s1").withName("111")....create();
这种用法的主要原因是编译时的兼容性维护。 但是由于java中的类型擦除,mockito不能支持具有RETURNS_MOCKS和RETURNS_DEEP_STUBS选项的链中的泛型:
Builder/*<ServerActionBuilder>-erasured generic*/ b = configurationBuilder.newServerAction("s1");
b.withName("111")...create();
上面示例中的结果应该是ServerAction,但在mockito中它是生成类的Object。
请参阅Issue: Can not Return deep stubs from generic method that returns generic type #484