Android Studio Arctic Fox 无法 运行 使用 mockk 配置 JUnit

Android Studio Arctic Fox unable to run JUnit configuration with mockk

我刚刚将 Android Studio 升级到最新版本。目前我猜我的一些测试 classes 产生了不稳定的测试结果,我想 运行 在 Android Studio 中重复模式,就像我在 Android Studio 4.2 中所做的那样。但是我发现我得到了以下异常

即使我尝试了一个简单的测试 class,我仍然遇到这个错误。我 运行 和 Gradle 测试 运行ner 并且它按预期工作但我不能用它来 运行 重复测试 class 看是否有任何片状结果在我的测试中 class

感谢任何评论或建议:)


java.lang.NoClassDefFoundError: io/mockk/proxy/MockKAgentFactory

    at io.mockk.impl.JvmMockKGateway.<init>(JvmMockKGateway.kt:198)
    at io.mockk.impl.JvmMockKGateway.<clinit>(JvmMockKGateway.kt:186)
    at com.example.testCorrect(Student.kt:24)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:688)
    at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
    at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
    at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod[=12=](ExecutableInvoker.java:115)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke[=12=](ExecutableInvoker.java:105)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod(TestMethodTestDescriptor.java:210)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:206)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:131)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:65)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:129)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:127)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:143)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:129)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:127)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:143)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:129)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:127)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute[=12=](EngineExecutionOrchestrator.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:96)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:75)
    at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)
Caused by: java.lang.ClassNotFoundException: io.mockk.proxy.MockKAgentFactory
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
    ... 68 more
import io.mockk.mockk
import junit.framework.Assert.assertEquals
import org.junit.jupiter.api.Test

class StudentTest {
    @Test
    fun testCorrect() {
        val mockStudent = mockk<Student>()
        assertEquals(1,1)
    }
}

class Student(
    val name:String
)

更新:

我只是创建了一个Hello World 项目,并使用上面提到的简单配置。在“Gradle Test Runner”配置中,它有效。但是在“JUnit”配置中,出现了同样的错误

Caused by: java.lang.ClassNotFoundException: io.mockk.proxy.MockKAgentFactory
   at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
   at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
   at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)

这是错误的部分。 它是说 class not found 异常,这意味着在某处提到了 class 但如果未找到或不存在。 或者,如果您正在使用一个实现,请删除该实现并重新放置它们。 这对我有用。 甚至我也遇到了同样的问题。

我想到了两个不同的problem/solutions。

  1. 您可能忘记在您的 Gradle 配置中添加 mockk,如下所示:
testImplementation "io.mockk:mockk:{version}"

并且可能在以前的 Android Studio 中,它是从 Gradle 缓存中提供的。


  1. 我不知道为什么,但每次我第一次打开一个项目时,Arctic Fox 都会切换到我自定义安装的 JDK (1.8),并且在我的构建中遇到一些 CNF 异常。将其更改为嵌入式 JDK 后,一切正常。您可以转到 Preferences -> Build, Execution -> Build Tools -> Gradle 并将 Gradle SDK 更改为嵌入式 JDK。正如我在您的屏幕截图中看到的,您还 运行 使用自定义安装的 JDK 11 进行测试。但是,mockk 不在 JDK 中,所以我想我的第一个建议可能更适合。

您缺少测试运行器注释

@RunWith(MockitoJUnitRunner::class)

您还需要检查 build.gradle(app) 文件中的以下内容

testImplementation "org.mockito.kotlin:mockito-kotlin:3.2.0"
testImplementation 'org.mockito:mockito-inline:3.8.0'

您可以尝试将此添加到您的应用级别吗build.gradle:

testOptions {
    unitTests.all {
        useJUnitPlatform()
    }
}

android-gradle-plugin 在 IDE 项目导入期间删除了 运行 时间依赖性。早些时候 Android 工作室 had dedicated IDE feature that extended JUnit run configuration classpath to include runtime dependencies. Now you have to recover classpath yourself (or better avoid JUnit run configuration in Android projects). Android Studio moves to a direction that everything should be delegated to Gradle (e.g. see https://developer.android.com/studio/preview/features#bumblebee-unified-test-runner).

由于您使用的是 JUnit5,@RepeatedTest(10_000_000) 或类似选项可能是更简单的选择。

TL;博士;

MockKAgentFactory 可从 io.mockk:mockk-agent-api 获得。我添加了以下内容以使您的示例工作:

    testImplementation "io.mockk:mockk:1.12.0"
    testImplementation "io.mockk:mockk-agent-jvm:1.12.0"
    testImplementation group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: '1.5.30'

诀窍在 Android Gradle 插件中。它构建(至少)2 个类路径:compile 和 运行time。 IDE Android 插件(在 Android Studio 中)仅从编译类路径导入库(运行time 条目已删除)。当 运行ning 使用 Gradle 运行ner 进行测试时,IDE 将执行委托给 gradle,并且 Gradle 使用运行时类路径调用测试。当 运行ning 在 Android Studio 中使用 JUnit 进行测试时,JUnit 使用 IDE 模块的 运行time 类路径,正如 IDE(已经没有运行时间库,因为它们在导入过程中被删除了)。检查外部库部分以查看添加到 IDE 项目的确切内容。

如果项目是常规 java 项目,IDE 将添加 mockk-agent-jvm 及其传递依赖项 mockk-agent-api。请注意,mockk-agent-jvmio.mockk:mockkRUNTIME 依赖项(参见 https://repo1.maven.org/maven2/io/mockk/mockk/1.12.0/mockk-1.12.0.pom)。 android-gradle-plugin 删除了导入过程中的 运行 时间依赖性。当 运行ning from IDE with gradle 运行 配置时,您可以在任何测试方法的开头设置断点并检查堆栈跟踪。完整测试 运行时间类路径在 gradle 调用 JUnitRunner 前一帧可用。例如。: