I want to add some test files to my test folder because I want to simulate some JSON file loading. The problem is that last Robolectric version (2.4) looks like it doesn't find the test-resources path (I get a NPE), but with Robolectric 2.3 it does.
This is how my project looks like:
In the Res class (used by the tests), I load the JSON that way:
public static String str(String path) throws IOException {
InputStream is = null;
try {
is = Res.class.getResourceAsStream(path); // "is" IS NULL!
return new String(ByteStreams.toByteArray(is)); // ERROR HERE
} finally {
if (is != null) {
is.close();
}
}
}
public static JsonReader json(String path) throws IOException {
return new JsonReader(new StringReader(str("/contact.json")));
}
And that is my build.gradle file:
buildscript {
// ...
dependencies {
classpath 'org.robolectric:robolectric-gradle-plugin:1.0.1'
}
}
apply plugin: 'com.android.application'
apply plugin: 'org.robolectric'
robolectric {
// ...
include '**/*Test.class'
ignoreFailures true
// ...
}
android {
compileSdkVersion 21
buildToolsVersion "22"
defaultConfig {
applicationId "com.ph"
minSdkVersion 15
targetSdkVersion 21
versionCode 9
versionName '4.1'
}
sourceSets {
androidTest {
setRoot('src/test')
res.srcDirs = [ 'src/test/resources' ]
}
test {
setRoot('src/test')
res.srcDirs = [ 'src/test/resources' ]
}
}
}
dependencies {
compile 'com.android.support:support-v4:22.0.0'
compile 'joda-time:joda-time:2.7'
compile 'com.google.guava:guava:18.0'
compile files('libs/gcm.jar')
compile 'org.codehaus.jackson:jackson-core-asl:1.9.13'
compile 'org.codehaus.jackson:jackson-mapper-asl:1.9.13'
compile 'org.slf4j:slf4j-api:1.7.10'
compile 'com.jakewharton:butterknife:6.1.0'
provided 'com.squareup.dagger:dagger-compiler:1.2.2'
compile 'com.squareup.dagger:dagger:1.2.2'
// ================== TESTING LIBRARIES ======================
testCompile 'junit:junit:4.12'
testCompile 'org.mockito:mockito-core:1.10.19'
testCompile ('org.robolectric:robolectric:2.4') {
exclude module: 'classworlds'
exclude module: 'commons-logging'
exclude module: 'httpclient'
exclude module: 'maven-artifact'
exclude module: 'maven-artifact-manager'
exclude module: 'maven-error-diagnostics'
exclude module: 'maven-model'
exclude module: 'maven-project'
exclude module: 'maven-settings'
exclude module: 'plexus-container-default'
exclude module: 'plexus-interpolation'
exclude module: 'plexus-utils'
exclude module: 'wagon-file'
exclude module: 'wagon-http-lightweight'
exclude module: 'wagon-provider-api'
}
testCompile 'com.squareup:fest-android:1.0.+'
testCompile 'org.bouncycastle:bcprov-jdk15on:1.50'
testCompile 'com.jakewharton:butterknife:6.1.0'
testCompile 'com.google.android:android:4.1.1.4'
}
And that is the error message:
java.lang.NullPointerException
at com.google.common.base.Preconditions.checkNotNull(Preconditions.java:210)
at com.google.common.io.ByteStreams.copy(ByteStreams.java:65)
at com.google.common.io.ByteStreams.toByteArray(ByteStreams.java:115)
at com.ph.Res.str(Res.java:17)
at com.ph.Res.json(Res.java:26)
at com.ph.SyncTest.testContact(SyncTest.java:182)
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:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:236)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:158)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
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)
Any idea what is wrong with Robolectric 2.4? Or is it better to rollback to 2.3?
I guess your issue is related to an open issue at google. https://code.google.com/p/android/issues/detail?id=136013
There exist also a workaround here an unmodified copy from post #10
import groovy.json.StringEscapeUtils
gradle.projectsEvaluated {
def variants = android.applicationVariants.collect()
tasks.withType(Test) { task ->
try {
variants.each { variant ->
def buildTypeName = variant.buildType.name.capitalize()
def productFlavorNames = variant.productFlavors.collect { it.name.capitalize() }
if (productFlavorNames.isEmpty()) {
productFlavorNames = [""]
}
def productFlavorName = productFlavorNames.join('')
def flavor = StringUtils.uncapitalize(productFlavorName)
def variationName = "${productFlavorName}${buildTypeName}"
if (task.name.contains(variationName)) {
def variationPath = variant.buildType.name;
if (StringUtils.isNotEmpty(productFlavorName)) {
variationPath = StringUtils.uncapitalize(productFlavorName) + "/" + variationPath
}
def copyTestResourcesTask = project.tasks.create("copyTest${variationName}Resources", Copy)
copyTestResourcesTask.from("${projectDir}/src/test/resources")
copyTestResourcesTask.into("${buildDir}/intermediates/classes/test/${variationPath}")
// Makes the test task depend on the copy test resource variation task
task.dependsOn(copyTestResourcesTask)
variants.remove(variant)
throw new Exception("Break") // Breaking the loop
}
}
} catch (Exception e) {} // Just drop the exception
}
}
and here you can find a working example https://github.com/nenick/android-gradle-template/blob/master/App/build.gradle
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With