Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to unit test http request android

I have used library Robolectric another possible framework. Http client for Android http://loopj.com/android-async-http/

static AsyncHttpClient client = new AsyncHttpClient();

public static void getData (final ServerCallback callback) {

    client.get("http://httpbin.org/get", new AsyncHttpResponseHandler() {

        @Override
        public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
            callback.onSuccess(statusCode, new String(responseBody));
        }

        @Override
        public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
            callback.onFailure(statusCode, new String(responseBody));
        }

    });
}

Test Class:

@RunWith(RobolectricTestRunner.class)
public class ApiTest{

@Test
public void testgetData () {

}

}

interface

public interface ServerCallback {
    // Api detect connection
    void onSuccess(int statusCode, String response);
    void onFailure(int statusCode, String response);
}
like image 975
Roma Darvish Avatar asked Dec 02 '16 12:12

Roma Darvish


People also ask

How can write unit test cases for activity in Android?

unit tests can be written under test java package, and instrumental tests can be written under androidTest package. You can then access UI widgets using Espresso ViewMatchers and then you can apply actions on them using ViewActions . Check documentation for further help. Show activity on this post.


1 Answers

Роман,

I'll provide a general answer to get you going in the right direction. My preferred method of testing http requests is to use the square okhttp mockwebserver. Review the project's unit tests if you have questions on their use.

In your particular case, there are a couple of things to address:

  • You'll need to override the base url being used in tests
  • The android-async-http library is asynchronous, however, to run a consistent unit test, you'll want the request/response to be synchronous

So, following your example, let's setup your test client as follows:

public class TestHttpClient {
    // package-local client that can be set in tests
    static AsyncHttpClient client = new AsyncHttpClient(); 
    // package-local baseUrl that can be set in tests
    static String baseUrl = "http://pastbin.org/";  

    public static void getData(final ServerCallback callback) {
        String url = baseUrl + "get";
        client.get(url, new AsyncHttpResponseHandler() {
            @Override
            public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
                callback.onSuccess(statusCode, new String(responseBody));
            }

            @Override
            public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
                callback.onFailure(statusCode, new String(responseBody));
            }
        });
    }
}

To test the TestHttpClient, use the MockWebServer to spin up a server for the test and setup the client to make a request to the server:

@RunWith(RobolectricTestRunner.class)
@Config(manifest = Config.NONE, sdk = Build.VERSION_CODES.LOLLIPOP)
public class TestHttpRequestTest {

    @Rule
    public MockWebServer mockWebServer = new MockWebServer();

    @Test
    public void getData_onSuccess_doesSomething() throws InterruptedException {
        // Here we are creating a mock ServerCallback.  We will use
        // this mock object to verify the callback is invoked
        ServerCallback callback = mock(ServerCallback.class);

        // To test the client, we need to send a request to the mock mockWebServer.
        // The MockWebServer spins up an actual backend to handle calls.  You MUST
        // setup the client to use the base Url of the mockWebServer instead of
        // the actual url e.g.: http://httpbin.org.
        TestHttpClient.baseUrl = mockWebServer.url("/").toString();

        // For testing, use a synchronous client so that we can get the response before
        // the test completes.
        TestHttpClient.client = new SyncHttpClient();

        // Set up the mockWebServer to return a MockResponse with
        // some data in the body. This data can be whatever you want... json, xml, etc.
        // The default response code is 200.
        mockWebServer.enqueue(new MockResponse().setBody("success"));
        // To simulate an error
        // mockWebServer.enqueue(new MockResponse().setResponseCode(500).setBody("error"));

        TestHttpClient.getData(callback); // calling the method under test

        verify(callback).onSuccess(200, "success"); // using verify of mockito
    }
}

Notes:

  • The async http client library requires some android system components to work correctly, so you MUST use the @RunWith(...) annotation
  • MockWebServer requires the @Config(sdk = 21) with sdk set to v21 or above to work with Robolectric.

To include the mockwebserver & mockito in your project, add the following to build.gradle

dependencies {
        testCompile 'com.squareup.okhttp3:mockwebserver:3.2.0'
        testCompile 'org.mockito:mockito-core:1.10.19'
    }

Happy testing!!!

like image 157
abest Avatar answered Oct 18 '22 21:10

abest