I have a multimodule project where tests sometimes fail when run in gradle's parallel mode. When this happens, tests from the first executed submodule fail, but following submodules' tests pass.
The failing tests all show the following stacktrace:
java.lang.NoClassDefFoundError: android/content/pm/PackageManager$NameNotFoundException
at java.lang.Class.getDeclaredConstructors0(Native Method)
at java.lang.Class.privateGetDeclaredConstructors(Class.java:2671)
at java.lang.Class.getConstructor0(Class.java:3075)
at java.lang.Class.getConstructor(Class.java:1825)
at org.robolectric.RobolectricTestRunner.getHooksInterface(RobolectricTestRunner.java:461)
at org.robolectric.RobolectricTestRunner.beforeTest(RobolectricTestRunner.java:300)
...
Caused by: java.lang.ClassNotFoundException: couldn't load android.content.pm.PackageManager$NameNotFoundException
at org.robolectric.internal.bytecode.SandboxClassLoader.getByteCode(SandboxClassLoader.java:195)
at org.robolectric.internal.bytecode.SandboxClassLoader.maybeInstrumentClass(SandboxClassLoader.java:138)
at org.robolectric.internal.bytecode.SandboxClassLoader.findClass(SandboxClassLoader.java:131)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 45 more
Caused by: java.util.zip.ZipException: invalid LOC header (bad signature)
at java.util.zip.ZipFile.read(Native Method)
at java.util.zip.ZipFile.access$1400(ZipFile.java:60)
at java.util.zip.ZipFile$ZipFileInputStream.read(ZipFile.java:734)
at java.util.zip.ZipFile$ZipFileInflaterInputStream.fill(ZipFile.java:434)
at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:158)
at java.io.FilterInputStream.read(FilterInputStream.java:133)
at java.io.FilterInputStream.read(FilterInputStream.java:107)
at org.robolectric.util.Util.copy(Util.java:21)
at org.robolectric.util.Util.readBytes(Util.java:38)
at org.robolectric.internal.bytecode.SandboxClassLoader.getByteCode(SandboxClassLoader.java:193)
... 49 more
It happens roughly 4 out of 10 runs.
When running gradle with -d option, it never fails. (So it is definitely a timing issue, as with -d the build takea a lot longer)
build tools version = 26.0.2
compileSdkVersion = 24
robolectric = 3.5.1
Any update on this?
Not really a concrete fix, but.. I've had success of resolving this issue by configuring Robolectric to not use runtime dependency resolution and download them before executing tests, like so:
configurations {
roboJellybean
roboKitkat
roboLollipop
}
dependencies {
// Add or remove any platform dependencies which you use
roboJellybean "org.robolectric:android-all:4.1.2_r1-robolectric-r1"
roboKitkat "org.robolectric:android-all:4.4_r1-robolectric-r2"
roboLollipop "org.robolectric:android-all:5.0.2_r3-robolectric-r0"
}
def robolectricDependencies = "${rootProject.buildDir.path}/robolectric"
task fetchRobolectricDependencies(type: Copy) {
from configurations.roboJellybean
from configurations.roboKitkat
from configurations.roboLollipop
into robolectricDependencies
}
subprojects {
afterEvaluate {
if (project.plugins.hasPlugin("com.android.application") || project.plugins.hasPlugin("com.android.library")) {
android {
testOptions.unitTests.all {
systemProperty 'robolectric.offline', 'true'
systemProperty 'robolectric.dependency.dir', robolectricDependencies
}
}
tasks.withType(Test) {
it.dependsOn fetchRobolectricDependencies
}
}
}
}
This way it could still run in parallel
Race condition while downloading android-all.jar I'm guessing鈥β爁irst thread (or process?) starts downloading via MavenDependencyResolver, which creates an empty or truncated file, which the second thread (or process?) uses prematurely.
Looks like a dupe of #2346.
Most helpful comment
Not really a concrete fix, but.. I've had success of resolving this issue by configuring Robolectric to not use runtime dependency resolution and download them before executing tests, like so:
This way it could still run in parallel