2

I have this retrofit call:

api.enqueue(new Callback<ResponseBody>() {

    @Override
    public void onFailure(Call<ResponseBody> call, Throwable t) {
        t.printStackTrace();
    }

    @Override
    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {

        try {
            if (response.isSuccessful()) { // 200 - 300
                String responseBody = response.body().string();
                ...
            }
        } catch (IOException e) {
            e.printStackTrace()
        }
    }
}

and want trigger the IOException in .string() with MockWebServer.

I tried

        MockResponse mockResponse = new MockResponse()
            .setResponseCode(200)
            .setSocketPolicy(SocketPolicy.DISCONNECT_DURING_RESPONSE_BODY)
            .setBody("{}");

but that ends up in OnFailure.

How can I trigger the IOException?

CarHa
  • 1,148
  • 11
  • 31

2 Answers2

2

Something like the following

  private void responseBodyFail(Protocol expectedProtocol) throws IOException {
    // Use a 2 MiB body so the disconnect won't happen until the client has read some data.
    int responseBodySize = 2 * 1024 * 1024; // 2 MiB
    server.enqueue(new MockResponse()
        .setBody(new Buffer().write(new byte[responseBodySize]))
        .setSocketPolicy(SocketPolicy.DISCONNECT_DURING_RESPONSE_BODY));
Yuri Schimke
  • 12,435
  • 3
  • 35
  • 69
0

Retrofit by default buffers the whole response into memory before passing it to you, meaning any IOException has been encountered (and passed to onFailure) before it has even constructed the Response<T> to give you.

You could make the test code work by adding the @Streaming annotation onto your interface method, however I suspect it's better to just leave it as-is and not attempt to test this case, since it evidently ought to not happen in practice.

You can see where they buffer it here and here

Angus H
  • 404
  • 3
  • 8