Robolectric + JaCoCo | Issue while running unit test and not generating code coverage

1.4k Views Asked by At

I have added Robolectric to get support of Shadow APIs for writing unit tests. Able to get coverage percentage through default Intellij code coverage tool in Android Studio.

Now trying to add JaCoCo to get enhanced coverage report.

I'm using file build.gradle(app) for putting
plugin as apply from: "$rootDir/jacoco.gradle" and
dependency as testImplementation 'org.robolectric:robolectric:4.3.1'


jacoco.gradle

apply plugin: 'jacoco'

/*jacoco {
    // https://bintray.com/bintray/jcenter/org.jacoco:org.jacoco.core
    toolVersion = "0.7.1.201405082137"
}*/

android {
    testOptions {

        unitTests {
            includeAndroidResources = true
        }

        unitTests.all {
            systemProperty 'user.home', System.getenv('HOME')
            jacoco {
                includeNoLocationClasses = true
            }
        }

        unitTests {
            returnDefaultValues = true
        }
    }
}

project.afterEvaluate {

    android.applicationVariants.all { variant ->
        def name = variant.name
        def testTaskName = "test${name.capitalize()}UnitTest"

        tasks.create(name: "${testTaskName}Coverage", type: JacocoReport, dependsOn: "$testTaskName") {
            group = "Reporting"
            description = "Generate Jacoco coverage reports for the ${name.capitalize()} build."

            classDirectories.from = fileTree(
                    dir: "${project.buildDir}/intermediates/classes/${name}",
                    excludes: ['**/R.class',
                               '**/R$*.class',
                               '**/*$ViewInjector*.*',
                               '**/*$ViewBinder*.*',
                               '**/BuildConfig.*',
                               '**/Manifest*.*']
            )

            sourceDirectories.from = files(['src/main/java'].plus(android.sourceSets[name].java.srcDirs))
            executionData.from = files("${project.buildDir}/jacoco/${testTaskName}.exec")

            reports {
                xml.enabled = true
                html.enabled = true
            }
        }
    }
}

While running test cases through CL/Run(Button) or Jenkins, getting same error

com.example.LoginActivityTest > initializationError FAILED
    java.lang.RuntimeException at AndroidJUnit4.java:121
        Caused by: java.lang.reflect.InvocationTargetException at null:-1
            Caused by: java.lang.NoSuchMethodError at ShadowProviders.java:25

com.example.HomeActivityTest > initializationError FAILED
    java.lang.RuntimeException at AndroidJUnit4.java:121
        Caused by: java.lang.reflect.InvocationTargetException at null:-1
            Caused by: java.lang.NoSuchMethodError at ShadowProviders.java:25



=*=*=*=*=*=*=*=*=*=*

java.lang.NoSuchMethodError: com.google.common.collect.ImmutableList.sortedCopyOf(Ljava/util/Comparator;Ljava/lang/Iterable;)Lcom/google/common/collect/ImmutableList;

    at org.robolectric.internal.bytecode.ShadowProviders.<init>(ShadowProviders.java:25)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at org.robolectric.util.inject.Injector.inject(Injector.java:250)
    at org.robolectric.util.inject.Injector.lambda$memoized$1(Injector.java:232)
    at org.robolectric.util.inject.Injector$MemoizingProvider.get(Injector.java:498)
    at org.robolectric.util.inject.Injector.getInstanceInternal(Injector.java:224)
    at org.robolectric.util.inject.Injector.getInstance(Injector.java:208)
    at org.robolectric.util.inject.Injector.getInstance(Injector.java:202)
    at org.robolectric.internal.SandboxTestRunner.<init>(SandboxTestRunner.java:78)
    at org.robolectric.RobolectricTestRunner.<init>(RobolectricTestRunner.java:103)
    at org.robolectric.RobolectricTestRunner.<init>(RobolectricTestRunner.java:98)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    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.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.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
    at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:33)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:49)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)






I appreciate your help!

1

There are 1 best solutions below

0
On

This is happening because there is more than one version of Guava in my classpath. One of them is being included by Gradle, and the other is likely part of some other jar file. You need to iterate over your jar file dependencies and figure out where the other guava is coming from, and then remove that.

For more information, please refer https://github.com/robolectric/robolectric/issues/5147