Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Mockito与机器人分子:“一个;ClassCastException在创建代理时发生;_Java_Android_Mockito_Robolectric - Fatal编程技术网

Java Mockito与机器人分子:“一个;ClassCastException在创建代理时发生;

Java Mockito与机器人分子:“一个;ClassCastException在创建代理时发生;,java,android,mockito,robolectric,Java,Android,Mockito,Robolectric,我开始在Mockito中遇到一个奇怪的ClassCastException,当它与Robolectric一起使用时。当我不使用Robolectric runner运行相同的测试时,一切正常,不会引发异常 下面是堆栈跟踪: org.mockito.exceptions.base.MockitoException: ClassCastException occurred when creating the proxy. You might experience classloading issue

我开始在Mockito中遇到一个奇怪的ClassCastException,当它与Robolectric一起使用时。当我不使用Robolectric runner运行相同的测试时,一切正常,不会引发异常

下面是堆栈跟踪:

org.mockito.exceptions.base.MockitoException: 
ClassCastException occurred when creating the proxy.
You might experience classloading issues, disabling the Objenesis cache *might* help (see MockitoConfiguration)
    at com.compassrosetech.ccs.android.test.ObservableCacheDispatcherTest.setUp(ObservableCacheDispatcherTest.java:63)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
    at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:236)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:158)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:74)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:211)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Caused by: java.lang.ClassCastException: kotlin.Function0$$EnhancerByMockitoWithCGLIB$$c0163e7f cannot be cast to org.mockito.cglib.proxy.Factory
    at org.mockito.internal.creation.jmock.ClassImposterizer.createProxy(ClassImposterizer.java:128)
    at org.mockito.internal.creation.jmock.ClassImposterizer.imposterise(ClassImposterizer.java:63)
    at org.mockito.internal.creation.jmock.ClassImposterizer.imposterise(ClassImposterizer.java:56)
    at org.mockito.internal.creation.CglibMockMaker.createMock(CglibMockMaker.java:23)
    at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:26)
    at org.mockito.internal.MockitoCore.mock(MockitoCore.java:51)
    at org.mockito.Mockito.mock(Mockito.java:1243)
    at org.mockito.internal.configuration.MockAnnotationProcessor.process(MockAnnotationProcessor.java:30)
    at org.mockito.internal.configuration.MockAnnotationProcessor.process(MockAnnotationProcessor.java:16)
    at org.mockito.internal.configuration.DefaultAnnotationEngine.createMockFor(DefaultAnnotationEngine.java:43)
    at org.mockito.internal.configuration.DefaultAnnotationEngine.process(DefaultAnnotationEngine.java:66)
    at org.mockito.internal.configuration.InjectingAnnotationEngine.processIndependentAnnotations(InjectingAnnotationEngine.java:71)
    at org.mockito.internal.configuration.InjectingAnnotationEngine.process(InjectingAnnotationEngine.java:55)
    at org.mockito.MockitoAnnotations.initMocks(MockitoAnnotations.java:108)
    ... 29 more
我使用的代码如下所示:

@RunWith(ApplicationTestRunner.class)
public class ObservableCacheDispatcherTest {

    @Mock
    private IDataMapper mockDataMapper;

    @Mock
    private ICache mockCache;

    @Mock
    private Function0<Object> mockLoader;

    private ObservableCacheDispatcher cacheDispatcher;


    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this); // <-- exception happens when executing this statement
        cacheDispatcher = new ObservableCacheDispatcher(mockCache, mockDataMapper);
    }

    ...
}
@RunWith(applicationestrunner.class)
公共类ObservableCacheDispatcherTest{
@嘲弄
私有IDataMapper mockDataMapper;
@嘲弄
私有icachemockcache;
@嘲弄
私有函数0模拟加载程序;
专用可观察调度程序缓存调度程序;
@以前
公共作废设置(){
initMocks(this);//18)
私有静态最终int MAX_SDK_受_ROBOLECTRIC支持=18;
私有静态最终字符串ANDROID_MANIFEST_PATH=“../app/src/main/AndroidManifest.xml”;
私有静态最终字符串ANDROID_MANIFEST_RES_PATH=“../app/src/main/RES”;
/**
*调用此构造函数以指定资源和AndroidManifest.xml的位置。
*
*@org.junit.runners.model.InitializationError
*/
公共应用程序启动程序(类testClass)引发初始化错误{
超级(测试类);
}
@覆盖受保护的AndroidManifest getAppManifest(配置){
返回新的AndroidManifest(Fs.fileFromPath(ANDROID_MANIFEST_PATH),
Fs.fileFromPath(ANDROID_MANIFEST_RES_PATH)){
@凌驾
public int getTargetSDK版本(){
返回ROBOLECTRIC支持的MAX_SDK_;
}
};
}
}

我应该修复什么来消除这个异常?

这实际上不是Kotlin的问题,而是Robolectric/Mockito。我相信它与类加载器有关。如果用任何其他库接口(既不是JDK,也不是项目的类)替换Kotlin类您将看到同样的异常。不幸的是,我没有看到解决方案,因为我不了解Robolectric的内部结构。您最好向Robolectric或Mockito团队询问这一点。

我也遇到了类似的问题。基本上,您有一些类需要Mockito模拟,而其他类需要PowerMock模拟。我通过添加
@PowerMockIngore
注释到我的测试类,并指定我想使用常规的“ol mockito”模拟的类。因此,在您的情况下,我认为添加注释:

@PowerMockIgnore({"com.package.IDataMapper", "com.package.ICache" ..etc})

会起作用。

解决方法小心!

请自担风险使用

首先,您必须重新定义kotlin函数接口:

interface TestFunction0<R> : Function0<R>
interface TestFunction1<T1, R> : Function1<T1, R>
接口测试函数0:Function0
接口TestFunction1:Function1
并嘲笑它:

val onUpdate: TestFunction0<Unit> = mock()
val-onUpdate:TestFunction0=mock()
如建议

'禁用对象缓存可能会有所帮助'

您可以创建覆盖配置。
这样做

  • 在src/test/java下创建一个名为org.mockito.configuration的包
  • 编写MockitoConfiguration类
类文件

package org.mockito.configuration;

public class MockitoConfiguration extends DefaultMockitoConfiguration {

  @Override
  public boolean enableClassCache() {
    return false;
  }
}

尝试重新构建代码。

我知道这个问题有点老了,但它可能会帮助寻找答案的人

添加

@PowerMockIgnore({ "org.mockito.*"})
之后

@RunWith(ApplicationTestRunner.class)

应该可以解决这个问题。

很有趣!我刚刚猜测与Kotlin/Robolectric有冲突。Kotlin是否取代了类加载器?我希望Kotlin专家加入对话,你能从这里检查解决方案吗@EugenMartynov很好,我添加了“Kotlin”tag,也许Kotlin的人会帮上忙。@EugenMartynov我尝试过这个解决方案,但没有帮助。我可能是因为我没有使用robolectric gradle插件,测试是在一个单独的纯Java模块中进行的。Alex,很抱歉在没有很好理解问题的情况下添加了链接。经过一些研究,当有人使用
PowerMock
(自定义类加载器)()。我将
mockito
robolectric
一起使用,没有任何问题。类似的代码对我来说很好。它是
robolectric
mockito
的特定版本吗?似乎是。我发现问题是由测试运行程序使用的不同类加载器引起的(Launcher/AsmInstrumentingClassLoader)和mockito的classloader(SearchingClassLoader),所以存根类是通过一个代理类生成的(我们试图强制转换到这个代理类)是由另一个加载的。它需要更多的调查,我很确定Mockito或Robolectric团队可以做得更好。等等!是不是
Launcher/AsmInstrumentingClassLoader
来自android gradle插件,而不是
Robolectric
?你使用什么版本的Mockito?实际上并不重要。Mockito和Robol都是ectric使用类加载器,在不同的类加载器中有两个相同的类实例,它们会由于ClassCastException而导致测试失败。也许有一些解决方法,但是我不知道当
PowerMock
被添加到我开始出现此错误的图片中时会出现问题。这甚至不会编译
@RunWith(ApplicationTestRunner.class)