java Mockito ClassCastException
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10324063/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Mockito ClassCastException
提问by aces.
The method I want to test has a for loop with logic for each element in bList:
我要测试的方法有一个 for 循环,其中包含 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=251and http://code.google.com/p/mockito/issues/detail?id=107
我搜索了一个解决方案并遇到了一些链接:http: //code.google.com/p/mockito/issues/detail? id= 251和 http://code.google.com/p/mockito/issues /详细信息?id=107
回答by Tim Pote
As this link you postedindicates, you've encountered a bug with Answers.RETURNS_DEEP_STUBS
.
正如您发布的此链接所示,您遇到了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.
我实际上没有看到任何理由RETURNS_DEEP_STUBS
在您的示例代码中实际使用。您真的应该尝试评估是否需要深存根,因为正如Mockito 文档所说,“每次模拟返回模拟时,仙女都会死亡。” 所以如果可以的话,把它去掉,你的例子就会起作用。
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:
但是,如果您坚持使用深存根,则可以通过将方法调用的返回值向上转换为Object
. 例如,将代码中的违规行替换为:
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:
尽管如此,我个人同意@jhericks。最好的解决方案可能是使用ArrayList
包含您的 mock的实际而不是 mocking 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
}
}
回答by Leonid Gorshkov
Unfortunately this is not possible
不幸的是这是不可能的
Case: tests on API:
案例:API测试:
interface ConfigurationBuilder {...}
configurationBuilder.newServerAction("s1").withName("111")....create();
Main reason of this usage is compatibility maintenance on compile time. But mockito cannot support generics in chains with RETURNS_MOCKS and RETURNS_DEEP_STUBS options due to type erasure in java:
这种用法的主要原因是编译时的兼容性维护。但是由于 java 中的类型擦除,mockito 不能支持具有 RETURNS_MOCKS 和 RETURNS_DEEP_STUBS 选项的链中的泛型:
Builder/*<ServerActionBuilder>-erasured generic*/ b = configurationBuilder.newServerAction("s1");
b.withName("111")...create();
Result in example above should be ServerAction but in mockito it is Object of generated class.
上面例子中的结果应该是 ServerAction 但在 mockito 中它是生成的类的对象。
see Issue: Can not Return deep stubs from generic method that returns generic type #484