Calling Apache DefaultHttpClient results in "java.lang.RuntimeException: Stub!"

I am immersed in the development of Android. I have a project that will interact with a RESTful resource, and I'm trying to figure out how to make a basic GET with parameters via HTTP. From everything I've read, consensus seems to be favored by HTTPClient through HttpURLConnection.

I wrote a wrapper class with a method that creates an instance of a key object for a request using HTTPClient:

public String get() { String responseString = null; HttpClient client = new DefaultHttpClient(); HttpGet get = new HttpGet(); try { get.setURI(new URI(this.baseURL())); } catch (URISyntaxException e1) { e1.printStackTrace(); } HttpResponse response; try { response = client.execute(get); responseString = readResponse(response.getEntity()); if(response != null) { System.out.println(responseString); } } catch(ClientProtocolException e) { e.printStackTrace(); } catch(IOException e) { e.printStackTrace(); } return responseString; 

}

String HttpClient client = new DefaultHttpClient(); throws the following exception:

 java.lang.RuntimeException: Stub! at org.apache.http.impl.client.AbstractHttpClient.<init>(AbstractHttpClient.java:5) at org.apache.http.impl.client.DefaultHttpClient.<init>(DefaultHttpClient.java:7) at org.rcindustries.appmap.RestClient.get(RestClient.java:54) at org.rcindustries.appmap.test.functional.RestClientTest.shouldReturnSomeJSon(RestClientTest.java:26) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) at org.junit.runners.ParentRunner.run(ParentRunner.java:236) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 

Each example I saw for HttpClient uses a similar structure to create GET and POST. Is the Apache Commons library bundled with the Android SDK significantly different from the standard library?

+4
source share
4 answers

I think this is an Android way of telling you that you cannot run this unit test on this platform. Unit tests that are related to interaction with the Android platform (for example, in this case on the network) should be run on a real Android device or a functioning Android emulator.

Apparently you are running unit tests against stub classes in the Android SDK.

+6
source

For those who might be interested, I came across a similar problem - although instead of HttpClient I was getting stub errors for DateUtils .

Stephen seems to be absolutely right - the classes included in the Android platform need an emulator: http://simpleprogrammer.com/2010/07/27/the-best-way-to-unit-test-in-android/

A really summary of the above link:

In fact, all methods are crossed out to throw an exception with the message "Stub!". when you call them. How cute.

Real versions of android.jar live on an emulator or on your real Android device.

Therefore, you can unit test ...

  • on the emulator - get the full Android platform, the "real" Android environment, etc. (but without the capabilities of the usual Java unit test tools - for example, JMock)

OR

  • with JVM - faster, can use unit test helpers such as JMock, etc., however, you cannot test everything that depends on the Android platform.
+8
source

This happens when using Proguard and the com.apache.http.legacy library in the Android SDK 23.

It worked after I added this to my Proguard configuration:

 -keep class org.apache.http.** { *; } -keep class org.apache.commons.codec.** { *; } -keep class org.apache.commons.logging.** { *; } -keep class android.net.compatibility.** { *; } -keep class android.net.http.** { *; } -keep class com.android.internal.http.multipart.** { *; } -dontwarn org.apache.http.** -dontwarn android.webkit.** 

This allows the Apache system implementation to correctly override stubs compiled into the application.

+2
source

This stream is old, but for those who don’t know, Robolectric solves this problem for testing.

0
source

All Articles