android - Kotlin JaCoCo,无覆盖 -> IllegalClassFormatException ...请提供原始的非仪器类

标签 android gradle kotlin code-coverage jacoco

kotlin 版本: 1.3.61

Android Gradle 插件: 3.5.3

JaCoCo 版本: 0.8.4.201905082037(默认android gradle版本)

项目:
https://github.com/goldy1992/Mp3Player/tree/feature/issue-112/migrate-to-kotlin

我有一个 多模块 gradle 项目 和:
2种口味:全,自动化
2 种构建类型:发布、调试

我正在将所有内容迁移到 kotlin。

模块结构

  • commons [android 库](按预期工作,测试覆盖率)
  • 客户端测试支持(用于测试 Activity 的实现)
  • 客户端 [android 库](无覆盖)-> 依赖于 commons,client-test-support
  • service-test-support(用于 Activity 的测试实现)
  • 服务 [android 库](无覆盖)-> 依赖于 commons,service-test-support
  • app [android 应用] 没有测试

  • 对于这篇文章的上下文,我只对 感兴趣单元测试

    测试按预期运行,但是由于部分(不是全部)kotlin 编译的类被识别为“仪表类”,因此没有生成覆盖率

    这些错误出现在测试即将成为许多类的以下打印输出的地方:
        java.lang.instrument.IllegalClassFormatException: Error while instrumenting com/github/goldy1992/mp3player/client/views/viewholders/MediaPlayerTrackViewHolder.
            at org.jacoco.agent.rt.internal_035b120.CoverageTransformer.transform(CoverageTransformer.java:93)
            at sun.instrument.TransformerManager.transform(TransformerManager.java:188)
            at sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:428)
            at java.lang.ClassLoader.defineClass1(Native Method)
            at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
            at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
            at java.net.URLClassLoader.defineClass(URLClassLoader.java:468)
            at java.net.URLClassLoader.access$100(URLClassLoader.java:74)
            at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
            at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
            at java.security.AccessController.doPrivileged(Native Method)
            at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
            at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
            at java.lang.Class.getDeclaredFields0(Native Method)
            at java.lang.Class.privateGetDeclaredFields(Class.java:2583)
            at java.lang.Class.getDeclaredFields(Class.java:1916)
            at org.junit.runners.model.TestClass.getSortedDeclaredFields(TestClass.java:77)
            at org.junit.runners.model.TestClass.scanAnnotatedMembers(TestClass.java:70)
            at org.junit.runners.model.TestClass.<init>(TestClass.java:57)
            at org.junit.runners.ParentRunner.createTestClass(ParentRunner.java:88)
            at org.junit.runners.ParentRunner.<init>(ParentRunner.java:83)
            at org.junit.runners.BlockJUnit4ClassRunner.<init>(BlockJUnit4ClassRunner.java:65)
            at org.robolectric.internal.SandboxTestRunner.<init>(SandboxTestRunner.java:71)
            at org.robolectric.RobolectricTestRunner.<init>(RobolectricTestRunner.java:101)
            at org.robolectric.RobolectricTestRunner.<init>(RobolectricTestRunner.java:96)
            at sun.reflect.GeneratedConstructorAccessor5.newInstance(Unknown Source)
            at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
            at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
            at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104)
            at org.junit.vintage.engine.discovery.DefensiveAllDefaultPossibilitiesBuilder$DefensiveAnnotatedBuilder.buildRunner(DefensiveAllDefaultPossibilitiesBuilder.java:113)
            at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86)
            at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
            at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
            at org.junit.vintage.engine.discovery.DefensiveAllDefaultPossibilitiesBuilder.runnerForClass(DefensiveAllDefaultPossibilitiesBuilder.java:56)
            at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
            at org.junit.vintage.engine.discovery.TestClassRequestResolver.createRunnerTestDescriptor(TestClassRequestResolver.java:55)
            at org.junit.vintage.engine.discovery.VintageDiscoverer.lambda$discover$0(VintageDiscoverer.java:53)
            at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
            at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
            at java.util.Iterator.forEachRemaining(Iterator.java:116)
            at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
            at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
            at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
            at java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:312)
            at java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:742)
            at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
            at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
            at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
            at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
            at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
            at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
            at org.junit.vintage.engine.discovery.VintageDiscoverer.discover(VintageDiscoverer.java:55)
            at org.junit.vintage.engine.VintageTestEngine.discover(VintageTestEngine.java:62)
            at org.junit.platform.launcher.core.DefaultLauncher.discoverEngineRoot(DefaultLauncher.java:168)
            at org.junit.platform.launcher.core.DefaultLauncher.discoverRoot(DefaultLauncher.java:155)
            at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
            at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:102)
            at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:82)
            at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:78)
            at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.lang.reflect.Method.invoke(Method.java:498)
            at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
            at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
            at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
            at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
            at com.sun.proxy.$Proxy2.stop(Unknown Source)
            at org.gradle.api.internal.tasks.testing.worker.TestWorker.stop(TestWorker.java:132)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.lang.reflect.Method.invoke(Method.java:498)
            at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
            at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
            at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:182)
            at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:164)
            at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:412)
            at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
            at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
            at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
            at java.lang.Thread.run(Thread.java:748)
        Caused by: java.io.IOException: Error while instrumenting com/github/goldy1992/mp3player/client/views/viewholders/MediaPlayerTrackViewHolder.
            at org.jacoco.agent.rt.internal_035b120.core.instr.Instrumenter.instrumentError(Instrumenter.java:158)
            at org.jacoco.agent.rt.internal_035b120.core.instr.Instrumenter.instrument(Instrumenter.java:108)
            at org.jacoco.agent.rt.internal_035b120.CoverageTransformer.transform(CoverageTransformer.java:91)
            ... 86 more
        Caused by: java.lang.IllegalStateException: Cannot process instrumented class com/github/goldy1992/mp3player/client/views/viewholders/MediaPlayerTrackViewHolder. Please supply original non-instrumented classes.
            at org.jacoco.agent.rt.internal_035b120.core.internal.instr.InstrSupport.assertNotInstrumented(InstrSupport.java:237)
            at org.jacoco.agent.rt.internal_035b120.core.internal.instr.ClassInstrumenter.visitField(ClassInstrumenter.java:55)
            at org.jacoco.agent.rt.internal_035b120.asm.ClassVisitor.visitField(ClassVisitor.java:287)
            at org.jacoco.agent.rt.internal_035b120.asm.ClassReader.readField(ClassReader.java:906)
            at org.jacoco.agent.rt.internal_035b120.asm.ClassReader.accept(ClassReader.java:683)
            at org.jacoco.agent.rt.internal_035b120.asm.ClassReader.accept(ClassReader.java:400)
            at org.jacoco.agent.rt.internal_035b120.core.instr.Instrumenter.instrument(Instrumenter.java:88)
            at org.jacoco.agent.rt.internal_035b120.core.instr.Instrumenter.instrument(Instrumenter.java:106)
            ... 87 more
    

    为了尝试找到问题的根源,我只运行了 客户端单元测试

    客户 build.gradle
    apply plugin: 'com.android.library'
    apply plugin: 'kotlin-android'
    apply plugin: 'kotlin-android-extensions'
    apply plugin: 'kotlin-kapt'
    apply plugin: 'de.mannodermaus.android-junit5'
    apply plugin: 'jacoco'
    
    android {
    
        compileSdkVersion TARGET_SDK_VERION
        buildToolsVersion BUILD_TOOLS_VERSION
    
        defaultConfig {
            minSdkVersion MIN_SDK_VERSION
            targetSdkVersion TARGET_SDK_VERION
            versionCode 1
            versionName "1.0"
            testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
            consumerProguardFiles 'consumer-rules.pro'
            vectorDrawables.useSupportLibrary = true
        }
    
        buildTypes {
            release {
                minifyEnabled true
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
            debug {
                debuggable true
                minifyEnabled false
                testCoverageEnabled = true
            }
        }
        flavorDimensions 'default'
        productFlavors {
            full {
                dimension = 'default'
            }
            automation {
                dimension = 'default'
            }
        }
    
        compileOptions {
            incremental = false
            sourceCompatibility JavaVersion.VERSION_1_8
            targetCompatibility JavaVersion.VERSION_1_8
        }
    
        kotlinOptions { jvmTarget = "1.8" }
    
    
        testOptions {
            execution 'ANDROID_TEST_ORCHESTRATOR'
            animationsDisabled true
    
            unitTests {
                includeAndroidResources = true
                returnDefaultValues = true
            }
    
            unitTests.all {
                testLogging {
                    events "passed", "skipped", "failed", "standardOut", "standardError"
                    outputs.upToDateWhen {false}
                    showStandardStreams = true
                }
            }
        }
    
        sourceSets {
            main.java.srcDirs += 'src/main/java'
            test.java.srcDirs += 'src/test/java'
            androidTest.java.srcDirs += 'src/androidTest/java'
        }
    }
    
    dependencies {
     implementation project(path: ':commons')
     testApi project(":client:testsupport")
    
     /* MORE DEPENDENCIES NOT RELEVANT TO ISSUE */
    }
    
    

    值得注意的是,我使用的是 Dagger 2.25.2

    执行数据目录 : ${projectRootDir}/client/build/jacoco/testFullDebugUnitTest.exec

    源目录 : ${projectRootDir}/client/src/main/java

    类(class)目录 : ${projectRootDir}/client/build/intermediates/javac/fullDebug/classes/, ${projectRootDir}/client/build/tmp/kotlin-classes/fullDebug/

    更新 1:
    从创建一个新分支并将客户端模块中的所有类和测试类重命名为 CLASS_NAME.kt.old 我可以确认 IllegalClassFormatException 之间似乎没有任何联系并且没有覆盖。因此,我将问题更新为以下

    更新 2:
    在对更新 1 进行进一步试验后,似乎异常消失了,并且覆盖率按预期计算当不依赖子(测试)模块时,即删除行 testApi project(":client:testsupport")从 gradle 文件。问题是我需要这个testsupport模块以执行我的 Activity 测试(当前未运行,因为它们在 .old 文件中,根据更新 1 ^^。

    根据 udate 2 更新的问题
    如何配置 JaCoCo 以支持 android 类的子模块测试实现,如 robolectric 团队在 this pull request 中所建议的那样.

    如果需要更多信息,将更新帖子

    最佳答案

    我刚刚遇到了同样的错误。
    经过一番调查,这似乎是Android Gradle插件中的一个错误,并且仅在使用com.android.library时发生.
    我在这里报告了它和更多细节:https://issuetracker.google.com/issues/178015739
    虽然 Android 团队没有修复它,但解决方法是配置

    jacoco {
        toolVersion = "0.7.9"
    }
    
    在 build.gradle
    它不会阻止错误被记录,但可以正确收集覆盖数据。

    关于android - Kotlin JaCoCo,无覆盖 -> IllegalClassFormatException ...请提供原始的非仪器类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59378618/

    相关文章:

    java - 如何在android中将字符串值保存为一个数组

    android - fragment 中的文本到语音

    java - 错误 :Error converting bytecode to dex: Cause: Dex cannot parse version 52 byte code

    android - Android构建错误 'Failed to read androiddebugkey from store'

    android - itextpdf-itextg Android Lint 错误

    android - KotterKnife - 某些类不能使用 bindView(R.id.example_id)

    android - Kivy ImportError : No module named android. 可运行

    android - 使用 volley android 在 RecyclerView 中解析 JSONArray

    android - 如何将左侧和右侧的 ItemDecoration 都应用于 RecyclerView 项目?

    enums - 如何在 Kotlin 中为枚举创建 "static"方法?