下面的测试类包含我的项目的复杂类层次结构的简化版本,它基于泛型。所有的3个测试,genericsFailure_NoSuchMethod()
,genericsFailure_ClassCast1()
,genericsFailure_ClassCast2()
都通过了jMockit 1.6的测试,但是从jMockit 1.7和1.8开始,我不断从jMockit内部得到不同种类的ClassCastException
和NoSuchMethodException
。
package tests;
import mockit.Cascading;
import mockit.Mocked;
import mockit.NonStrictExpectations;
import org.testng.annotations.Test;
public class JMockitTests
{
public static interface IAppBound<APP extends IApp<?, ?>>
{
APP getApp();
}
public static interface IBase<APP extends IApp<APP, ?>> extends IAppBound<APP>
{
}
public static interface IApp<APP extends IApp<APP, ?>, BACK extends IBack<APP>> extends IBase<APP>
{
BACK getBack();
}
public static interface IBack<APP extends IApp<APP, ?>> extends IBase<APP>
{
}
public static abstract class BaseImpl<APP extends AppImpl<APP, ?>> implements IBase<APP>
{
private APP app;
@Override
public APP getApp()
{
return app;
}
}
public static class AppImpl<APP extends AppImpl<APP, ?>, BACK extends BackImpl<APP>> extends BaseImpl<APP> implements IApp<APP, BACK>
{
private BACK b;
@Override
public BACK getBack()
{
return b;
}
}
public static class BackImpl<APP extends AppImpl<APP, ?>> extends BaseImpl<APP> implements IBack<APP>
{
private Registry<APP, BackImpl<APP>> reg;
public Registry<APP, BackImpl<APP>> getRegistry()
{
return reg;
}
@Override
public APP getApp()
{
return super.getApp();
}
}
public static class Registry<APP extends AppImpl<APP, ?>, BACK extends BackImpl<APP>>
{
public BACK getBack(APP app)
{
return null;
}
public BACK getBack(BACK app)
{
return null;
}
public BACK getBack(String app)
{
return null;
}
}
public static class SpecificApp extends AppImpl<SpecificApp, BackImpl<SpecificApp>>
{
}
@Test
public void genericsFailure_NoSuchMethod(@Mocked @Cascading AppImpl<?, ?> app, @Mocked @Cascading IBack<?> back)
{
new NonStrictExpectations()
{
{
back.getApp();
result = app;
}
};
}
@Test
public void genericsFailure_ClassCast1(@Mocked @Cascading BackImpl<SpecificApp> back)
{
SpecificApp app = new SpecificApp();
new NonStrictExpectations()
{
{
back.getRegistry().getBack(app);
result = back;
}
};
}
@Test
public void genericsFailure_ClassCast2(@Mocked @Cascading BackImpl<SpecificApp> back)
{
SpecificApp app = new SpecificApp();
new NonStrictExpectations()
{
{
back.getApp();
result = app;
}
};
}
}
我认为要么是jmockit对泛型的处理发生了变化,要么是我完全忽略了jmockit的基本概念。当然,我再次咨询了version history和documentation两个问题,但没有任何东西吸引我的眼球。
我必须提到,我已经用JDK8和JDK7测试了这个问题,仍然存在这个问题。我正在运行testng(6.8.6)作为eclipse插件。
以下是testng的测试结果:
FAILED: genericsFailure_ClassCast1(tests.JMockitTests$BackImpl@883ce7)
java.lang.ClassCastException: java.lang.Object cannot be cast to tests.JMockitTests$BackImpl
at tests.JMockitTests$Registry.getBack(JMockitTests.java)
at tests.JMockitTests$2.<init>(JMockitTests.java:113)
at tests.JMockitTests.genericsFailure_ClassCast1(JMockitTests.java:110)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.lang.reflect.Method.invoke(Method.java:483)
FAILED: genericsFailure_ClassCast2(tests.JMockitTests$BackImpl@a7e666)
java.lang.ClassCastException: sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to java.lang.Class
at tests.JMockitTests$BackImpl.getApp(JMockitTests.java)
at tests.JMockitTests$3.<init>(JMockitTests.java:127)
at tests.JMockitTests.genericsFailure_ClassCast2(JMockitTests.java:124)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.lang.reflect.Method.invoke(Method.java:483)
FAILED: genericsFailure_NoSuchMethod(tests.JMockitTests$AppImpl@4f6be2, tests.$Impl_IBack@aac163)
java.lang.RuntimeException: java.lang.NoSuchMethodException: tests.JMockitTests$IBack.getApp()
at tests.JMockitTests$1.<init>(JMockitTests.java:99)
at tests.JMockitTests.genericsFailure_NoSuchMethod(JMockitTests.java:96)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.lang.reflect.Method.invoke(Method.java:483)
Caused by: java.lang.NoSuchMethodException: tests.JMockitTests$IBack.getApp()
at java.lang.Class.getDeclaredMethod(Class.java:2117)
... 4 more
如果有人能批准这件事,或者能让我找到解决办法,我将不胜感激。
编辑:我在项目上打开了一个issue (issue 350)来进一步跟踪这个。
最佳答案
我很惊讶这样的测试在jmockit 1.6中工作,因为在级联模拟期间,它对泛型没有太多的显式支持。
无论如何,自1.7以来的变化与仍然开放的issue 333有关。不过,这两个问题都将在jmockit 1.9中得到解决。
关于java - 具有复杂的通用类层次结构的ClassCastException和NoSuchMethodException,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23437406/