I am writing unit tests to cover API with tests. I use robolectric and gradle, also have to add multidex to support large apk build. Unexpectedly I can not run the test and can not understand the stacktrace
java.lang.NullPointerException: parentLoader == null && !nullAllowed
at java.lang.ClassLoader.<init>(ClassLoader.java:210)
at java.lang.ClassLoader.<init>(ClassLoader.java:202)
at java.security.SecureClassLoader.<init>(SecureClassLoader.java:48)
at java.net.URLClassLoader.<init>(URLClassLoader.java:710)
at java.net.URLClassLoader.<init>(URLClassLoader.java:555)
at org.codehaus.classworlds.RealmClassLoader.<init>(RealmClassLoader.java:94)
at org.codehaus.classworlds.RealmClassLoader.<init>(RealmClassLoader.java:83)
at org.codehaus.classworlds.DefaultClassRealm.<init>(DefaultClassRealm.java:116)
at org.codehaus.classworlds.ClassWorld.newRealm(ClassWorld.java:100)
at org.apache.maven.artifact.ant.AbstractArtifactTask.getContainer(AbstractArtifactTask.java:490)
at org.apache.maven.artifact.ant.AbstractArtifactTask.lookup(AbstractArtifactTask.java:457)
at org.apache.maven.artifact.ant.AbstractArtifactTask.initSettings(AbstractArtifactTask.java:290)
at org.apache.maven.artifact.ant.AbstractArtifactTask.execute(AbstractArtifactTask.java:750)
at org.robolectric.internal.dependency.MavenDependencyResolver.getLocalArtifactUrls(MavenDependencyResolver.java:40)
at org.robolectric.internal.dependency.CachedDependencyResolver.getLocalArtifactUrls(CachedDependencyResolver.java:43)
at org.robolectric.internal.InstrumentingClassLoaderFactory.getSdkEnvironment(InstrumentingClassLoaderFactory.java:39)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:187)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:54)
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:152)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
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.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at android.support.test.internal.runner.TestExecutor.execute(TestExecutor.java:59)
at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:262)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1837)
@RunWith(RobolectricGradleTestRunner.class)
@Config(application = TestApplication.class,
constants = BuildConfig.class,
sdk = 21)
public class ApiTest {
private MockWebServer webServer;
private IApi api;
private TestUtils testUtils;
@Before
public void setUp() throws Exception {
Log.d(App.TAG, "Test setUp");
testUtils = new TestUtils();
webServer = new MockWebServer();
webServer.start();
webServer.setDispatcher(new Dispatcher() {
@Override
public MockResponse dispatch(RecordedRequest request) throws InterruptedException {
MockResponse response;
if (request.getPath().equals("savingsgoals")) {
response = new MockResponse().setResponseCode(200)
.setBody(testUtils.readString("json/goals.json"));
} else if (request.getPath().equals("savingsgoals/" + TestApp.Const.GOAL_ID + "/feed")) {
response = new MockResponse().setResponseCode(200)
.setBody(testUtils.readString("json/feed.json"));
} else if (request.getPath().equals("savingsrules")) {
response = new MockResponse().setResponseCode(200)
.setBody(testUtils.readString("json/rules.json"));
} else if (request.getPath().equals("user/" + TestApp.Const.USER_ID)) {
response = new MockResponse().setResponseCode(200)
.setBody(testUtils.readString("json/user.json"));
} else {
response = new MockResponse().setResponseCode(404);
}
return response;
}
});
HttpUrl url = webServer.url("/");
api = ApiModule.getApiInterface(url.toString());
}
@Test
public void testGoals() throws Exception {
TestSubscriber<SavingsGoals> testSubscriber = new TestSubscriber();
api.getSavingsGoals().subscribe(testSubscriber);
testSubscriber.assertNoErrors();
testSubscriber.assertValueCount(1);
SavingsGoals goals = testSubscriber.getOnNextEvents().get(0);
goals.getSavingsGoals();
}
}
Do you have an idea what is root cause?
Here is my gradle build
androidTestCompile 'org.robolectric:robolectric:3.3.2'
androidTestCompile('com.squareup.okhttp:mockwebserver:2.7.0', {
exclude group: 'com.squareup.okio', module: 'okio'
})
androidTestCompile 'junit:junit:4.12'
UPDATE
Console output:
Error:Execution failed for task ':app:transformClassesWithDexForDebugAndroidTest'. > com.android.build.api.transform.TransformException: java.lang.RuntimeException: java.lang.RuntimeException: Unable to pre-dex 'D:\Users\John\.gradle\caches\modules-2\files-2.1\com.thoughtworks.xstream\xstream\1.4.8\520d90f30f36a0d6ba2dc929d980831631ad6a92\xstream-1.4.8.jar' to 'C:\workspace\TestRobolectricTest\app\build\intermediates\pre-dexed\androidTest\debug\xstream-1.4.8_54d21a03bcf95b493d9c102453945dde45691be3.jar'
allprojects {
tasks.withType(JavaCompile) {
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
}
}