Search code examples
androidunit-testingibm-mobilefirst

Mocking WLResponse throws ClassNotFoundException for HttpResponse


I'm in the process of writing unit tests for an Android project that uses MFP 7.1 and I'm attempting to test some functionality which takes an WLResponse object as an input. I'd like to mock this object as the only thing I need from it is the JSONObject that gets returned by calling its getResponseJSON method.

    JSONObject jsonObject = Mockito.mock(JSONObject.class);
    Mockito.when(jsonObject.toString()).thenReturn(person.toString());

    WLResponse wlResponse = Mockito.mock(WLResponse.class);
    Mockito.when(wlResponse.getResponseJSON()).thenReturn(jsonObject);

The issue is that when I call Mockito.mock(WLResponse.class) I get the following exception thrown at runtime:

java.lang.NoClassDefFoundError: org/apache/http/HttpResponse
at java.lang.Class.getDeclaredConstructors0(Native Method)
at java.lang.Class.privateGetDeclaredConstructors(Class.java:2671)
at java.lang.Class.getDeclaredConstructors(Class.java:2020)
at org.mockito.internal.creation.jmock.ClassImposterizer.setConstructorsAccessible(ClassImposterizer.java:75)
at org.mockito.internal.creation.jmock.ClassImposterizer.imposterise(ClassImposterizer.java:70)
at org.mockito.internal.creation.jmock.ClassImposterizer.imposterise(ClassImposterizer.java:56)
at org.mockito.internal.creation.CglibMockMaker.createMock(CglibMockMaker.java:23)
at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:26)
at org.mockito.internal.MockitoCore.mock(MockitoCore.java:51)
at org.mockito.Mockito.mock(Mockito.java:1243)
at org.mockito.Mockito.mock(Mockito.java:1120)
at com.ibm.mil.cafejava.GsonConverterTest.before(GsonConverterTest.java:26)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
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.RunBefores.evaluate(RunBefores.java:24)
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.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

Caused by: java.lang.ClassNotFoundException: org.apache.http.HttpResponse
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 38 more

I'm using the MFP 7.1 SDK that is provided through jcenter, specifically:

compile 'com.ibm.mobile.foundation:ibmmobilefirstplatformfoundation:7.1.0'

From what I can infer, WLResponse has a constructor which takes an org.apache.http.HttpResponse object as an argument. But looking at the dependencies that MFP uses, it relies on the android-async-http library, which in turn relies on the httpclient-android library. It is this second library which has the HttpResponse class that the first one uses, but the package it's located in is cz/msebera/android/httpclient/ and not org/apache/http/. Perhaps this could be the source of the error, since the WLResponse constructor is expecting org.apache.http.HttpResponse instead, preventing Mockito from being able to mock it.


Solution

  • This is probably due to the fact that Android 6.0 removes support for the Apache HTTP client. Assuming your compileSdkVersion is 23, try adding the following to your build.gradle:

    android {
        compileSdkVersion 23
        useLibrary  'org.apache.http.legacy'
    }