Loopj (AsyncHttpClient get method) doesnt return response in Android Unit Test

knagode picture knagode · Jul 10, 2013 · Viewed 8.7k times · Source

I am trying to create Unit test on Android project which is working with URL requests. I use loopj library but something doesn't work. Internet is enabled in my manifest:

<uses-permission android:name="android.permission.INTERNET" />

Java code in a test method:

    AsyncHttpClient client = new AsyncHttpClient();
    client.get("http://www.yahoo.com", new AsyncHttpResponseHandler() {
        @Override
        public void onSuccess(String response) {
            System.out.println(response); // <------ I never get here!?!?!
        }
    });

Folowing procedure (without loopj) works in same unit test method:

    URL yahoo;
    yahoo = new URL("http://www.yahoo.com/");
    BufferedReader in;
    in = new BufferedReader(new InputStreamReader(yahoo.openStream()));
        String inputLine;
    while ((inputLine = in.readLine()) != null) {
             System.out.println(inputLine);

            }
    in.close();

It seems like loopj requests dont work in unit test class but it works normal in basic Activity class. Any suggestion?

Answer

knagode picture knagode · Jul 16, 2013

The problem is since loopj uses android.os.AsyncTask which doesnt work in unit test environment.

Key to success is "runTestOnUiThread" method.

public void testAsyncHttpClient() throws Throwable {
  final CountDownLatch signal = new CountDownLatch(1);
  final AsyncHttpClient httpClient = new AsyncHttpClient();
  final StringBuilder strBuilder = new StringBuilder();

  runTestOnUiThread(new Runnable() { // THIS IS THE KEY TO SUCCESS
    @Override
    public void run() {
      httpClient
          .get(
              "https://api.twitter.com/1/users/show.json?screen_name=TwitterAPI&include_entities=true",
              new AsyncHttpResponseHandler() {
                @Override
                public void onSuccess(String response) {
                  // Do not do assertions here or it will stop the whole testing upon failure
                  strBuilder.append(response);
                }

                public void onFinish() {
                  signal.countDown();
                }
              });
    }
  });

  try {
    signal.await(30, TimeUnit.SECONDS); // wait for callback
  } catch (InterruptedException e) {
    e.printStackTrace();
  }

  JSONObject jsonRes = new JSONObject(strBuilder.toString());
  try {
    // Test your jsonResult here
    assertEquals(6253282, jsonRes.getInt("id"));
  } catch (Exception e) {

  }

  assertEquals(0, signal.getCount());
}

Ful thread: https://github.com/loopj/android-async-http/issues/173