MockWebServer's takeRequest() method takes long to response or hangs

11.2k views Asked by At

I'm using MockWebServer library in my Android JUnit tests. I'm testing an SDK that makes calls to a server. So I'm using MockWebServer to override these server URLs and capture what the SDK is sending to make assertions on it.

The problem that I'm running into is that if I try to do server.takeRequest() and assign it to a new RecordedRequest variable, the test hangs up on the second server.takeRequest() and sometimes, even on the first one -- if I run it on an emulator it hangs on the first server.takeRequest() method but if I run it on my physical Android device, it freezes on the second server.takeRequest() method.

public void testSomething() {
  final MockWebServer server = new MockWebServer();

  try {
    server.play();
    server.enqueue(new MockResponse().setBody("")
      .setResponseCode(HttpURLConnection.HTTP_INTERNAL_ERROR));
    server.enqueue(new MockResponse().setBody("")
      .setResponseCode(HttpURLConnection.HTTP_OK));
    server.enqueue(new MockResponse().setBody("")
      .setResponseCode(HttpURLConnection.HTTP_OK));

    URL url = server.getUrl("/");
    // This internal method overrides some of the hardcoded URLs 
    // within the SDK that I'm testing.
    Util.overrideUrls(url.toString()) 

    // Do some server calls via the SDK utilizing the mock server url.

    RecordedRequest requestFor500 = server.takeRequest();
    // Do some assertions with 'requestFor500'

    // Do some more server calls via the SDK utilizing the mock server url.

    /* 
     * This is the part where the JUnit test hangs or seems to go into 
     * an infinite loop and never recovers 
     */
    RecordedRequest requestAfter500Before200 = server.takeRequest();
  } catch {
    ...
  }
}

Am I doing something wrong or is this some type of bug with MockWebServer?

3

There are 3 answers

1
Prayag On

Add timeout to MockWebServer so that it does not hang server.takeRequest(1, TimeUnit.SECONDS);

0
Denys Kniazhev-Support Ukraine On

There seems to be a problem with MockWebServer's dispatch queue, which freezes for some reason when serving responses which are not 200 or 302. I have solved this by providing a custom dispatcher:

MockWebServer server = ...;

final MockResponse response = new MockResponse().setResponseCode(401);

server.setDispatcher(new Dispatcher() {
    @Override
    public MockResponse dispatch(RecordedRequest request) 
        throws InterruptedException {
        return response; // this could have been more sophisticated
    }
});

Tested with MockWebServer 2.0.0

0
dzikovskyy On

In my case, the issue was caused by using an HTTP (non-secure) connection instead of HTTPS (secure). The request never succeeded because of the exception:
java.net.UnknownServiceException: CLEARTEXT communication to localhost not permitted by network security policy.

Adding the android:usesCleartextTraffic="true" property to the test manifest file solved the problem.