Android
真机使用Mockito-1.10.19
+Dexmaker-1.2
在Mock
仅包内可见类时报告如下错误:
java.lang.UnsupportedOperationException: cannot proxy inaccessible class class com.yunos.tv.shake.biz.PackageAccessible
at com.android.dx.stock.ProxyBuilder.buildProxyClass(ProxyBuilder.java:269)
at com.android.dx.mockito.DexmakerMockMaker.createMock(DexmakerMockMaker.java:56)
at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:33)
at org.mockito.internal.MockitoCore.mock(MockitoCore.java:59)
at org.mockito.Mockito.mock(Mockito.java:1285)
at org.mockito.Mockito.mock(Mockito.java:1163)
at com.yunos.tv.shake.biz.PackageAccessibleTest.setUp(PackageAccessibleTest.java:17)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:176)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:555)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1853)
Caused by: java.lang.IllegalAccessError: Class com.yunos.tv.shake.biz.PackageAccessible extended by class PackageAccessible_Proxy is inaccessible (declaration of 'PackageAccessible_Proxy' appears in /data/data/com.yunos.tv.shake.biz.test/cache/Generated_179875952.jar)
at dalvik.system.DexFile.defineClassNative(Native Method)
at dalvik.system.DexFile.defineClass(DexFile.java:226)
at dalvik.system.DexFile.loadClassBinaryName(DexFile.java:219)
at dalvik.system.DexPathList.findClass(DexPathList.java:321)
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:54)
at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
at com.android.dx.stock.ProxyBuilder.loadClass(ProxyBuilder.java:284)
at com.android.dx.stock.ProxyBuilder.buildProxyClass(ProxyBuilder.java:266)
... 15 more
被测试类代码如下:
package com.yunos.tv.shake.biz;
class PackageAccessible {
}
注意上述被测试类前面没有声明public
,因此默认是default
访问,也就是包内可见。我们下面的测试代码跟被测试类属于同一个包名package com.yunos.tv.shake.biz
,因此,按理说,是可以正常访问的。
测试类的代码如下:
package com.yunos.tv.shake.biz;
import android.test.AndroidTestCase;
import org.mockito.Mockito;
public class PackageAccessibleTest extends AndroidTestCase {
protected void setUp() throws Exception {
super.setUp();
/*解决BUG dexcache == null (and no default could be found; consider setting the 'dexmaker.dexcache' system pr*/
System.setProperty(
"dexmaker.dexcache",
getContext().getCacheDir().getPath());
PackageAccessible packageAccessible = Mockito.mock(PackageAccessible.class);
}
}
这个问题只在ART
虚拟机下面发生异常,相同的代码在Dalvik
下面是完全正常的。
问题发生的原因暂时还不能确定,应该是ART
虚拟机实现功能的时候的不兼容导致的。
解决方法为在测试代码中声明一个继承被测试类的子类,并且把子类声明成public
。
如下:
package com.yunos.tv.shake.biz;
public class PackageAccessibleShadow extends PackageAccessible {
}
修改后的测试代码如下:
package com.yunos.tv.shake.biz;
import android.test.AndroidTestCase;
import org.mockito.Mockito;
public class PackageAccessibleTest extends AndroidTestCase {
protected void setUp() throws Exception {
super.setUp();
/*解决BUG dexcache == null (and no default could be found; consider setting the 'dexmaker.dexcache' system pr*/
System.setProperty(
"dexmaker.dexcache",
getContext().getCacheDir().getPath());
PackageAccessibleShadow packageAccessible = Mockito.mock(PackageAccessibleShadow.class);
}
}
即可解决上述问题。