Question

How is it possible to produce the same exception like during a real connection-error in robolectric tests?

I want to how the program acts if the network is currently not available. Is there a possibility to produce the same exception for my HttpClient?

I already tried:

Robolectric.getFakeHttpLayer().interceptHttpRequests(false); // with real network to a non existent IP

and

WifiManager wifiManager = (WifiManager) activity.getSystemService(Context.WIFI_SERVICE);
wifiManager.setWifiEnabled(false);

and

Robolectric.addPendingHttpResponse(404, null);

but none of them produces the same reactions like a real connection-loosing.

Thank you

Was it helpful?

Solution

I've checked Robolectric's FakeHttpLayer and haven't found way to simulate throwing an IOException.

So use mocking to make it working for you. First introduce HttpClientFactory (if you use HttpClient, you can use same approach for HttpUrlConnection):

public class HttpClientFactory {
    public HttpClient createClient() {
     return new DefaultHttpClient();
    }
}

And now in your networking layer use factory instead of constructors (let for simplicity assume that it is synchronous):

public class HttpTransportLayer {
    private final HttpClientFactory clientFactory;

    public HttpTransportLayer() {
        this(new HttpClientFactory());
    }

    // For tests only
    HttpTransportLayer(HttpClientFactory clientFactory) {
        this.clientFactory = clientFactory;
    }

    public String requestData(String url) {
        HttpClient client = factory.createClient();
        ...
    } 
}

So now you can in tests use Mockito:

HttpClient mockedClient = mock(HttpClient.class);

@Before
public void setUp() {
     HttpClientFactory factory = mock(HttpClientFactory.class);
     when(factory.createClient()).thenReturn(mockedClient);

     target = new HttpTransportLayer(factory);
}

@Test
public void whenIOExceptionThenReturnNull() {
    when(mockedClient.execute(any(HtptUriRequest.class))).thenThrow(new IOException());

    String data = target.requestData("http://google.com");

    assertThat(data).isNull();
}

That is dummy test and usually nobody will return null in case of error.

You could also task look to some dependency injection framework like Dagger to minimise injection code.

If you use any good framework for networking like Retrofit or Volley then it is even simpler - you don't need to mock anything and just invoke you error callback.

Hope it helps

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top