35

I want to simulate the no network case when using RetroFit and MockWebServer.

Im currently testing using Espresso and supplying the MockWebServers url to the RestAdapter before I start my tests. This works great for mocking server responses and so on but I cant see a simple way to script the java.net.ConnectException exception thrown when a device has no network. I can see the MockResponse allows throttling simulation and so on but not a custom exception.

I know I could go the root of mocking the actual web api interface used by retrofit but I would like to use the same approach as my other tests if possible by using MockWebServer.

I imagine I've just missed something simple :)

Thanks

Dori
  • 18,283
  • 17
  • 74
  • 116

6 Answers6

30

Retrofit has a retrofit-mock module which offers a MockRestAdapter class whose purpose is to simulate network delay and errors.

This is a used in conjunction with the normal RestAdapter to create an instance of your service. You can see a full example in the samples/mock-github-client/ folder of the repo: https://github.com/square/retrofit/tree/parent-1.9.0/retrofit-samples/mock-github-client

MockRestAdapter offers these APIs:

  • setDelay - Set the network round trip delay, in milliseconds.
  • setVariancePercentage - Set the plus-or-minus variance percentage of the network round trip delay.
  • setErrorPercentage - Set the percentage of calls to calculateIsFailure() that return true.

In your test, you can call setErrorPercentage(100) to guarantee that a network error will occur. By default the amount of time for the error to be thrown is anywhere from 0 to 3x the delay. Set the delay to 0 for instant results.

Diego Palomar
  • 6,958
  • 2
  • 31
  • 42
Jake Wharton
  • 75,598
  • 23
  • 223
  • 230
15

The easiest way to simulate network issues with MockWebServer is by setting the SocketPolicy to SocketPolicy.DISCONNECT_AT_START, SocketPolicy.NO_RESPONSE or etc:

MockWebServer server = new MockWebServer();

MockResponse response = new MockResponse()
  .setSocketPolicy(SocketPolicy.DISCONNECT_AT_START);

server.enqueue(response);

This way you can simulate network errors like connection prematurely closed before response or Timeout exceptions

7

to be clear with whe types of exceptions here you can see the differences:

Internet Connection Error

So you can get two types:

UnknownHostException - When you don't have internet or unknown host... to simulate this, set to the adapter an incorrect end point.

ConnectException - mockwebserver can throw a timeout exception. You can see how to do it here:

https://github.com/square/okhttp/tree/master/mockwebserver

Really I don't know how your code is, but I hope this is useful

Community
  • 1
  • 1
mromer
  • 1,867
  • 1
  • 13
  • 18
  • +1 thanks for answering but it does not really answer the question as I want to simulate no network as opposed to a timeout. Dispatchers interesting though. I wonder if i can throw the above exceptions though that... – Dori Jul 25 '14 at 12:33
  • seems I cant as the network exceptions are checked and the dispatcher only throws Inturrupted as per its interface – Dori Jul 25 '14 at 13:24
4

I don't know if it's useful, but you can simulate a timeout with MockWebServer:

String contentType = "Content-type: application/json";
MockResponse response = MockResponse().setResponseCode(statusCode).setBody(responseBody).addHeader(contentType);
MockWebServer proxy = new MockWebServer();
proxy.enqueue(response);
proxy.setBodyDelayTimeMs(timeoutDelay));
proxy.play(10000); //Number port - Important!!!

Note: Please, set HttpClient of your code (e.g. AsyncHttpClient) with that number port for testing purpose.

Jesús Castro
  • 2,061
  • 1
  • 22
  • 26
3

What worked for me is pointing the Retrofit URL (end-point) to a random non-existent host . I used "thisIsARandomHost.com" and bingo i was able to mock the unknown host exception.

For example : setAPP_URL = "http://thisIsARandomHost.com/";

Here , setAPP_URL is the string variable that contains my url which I pass on to retrofit , when I want to mock unknown host exception in my tests I set the url as above .For all other purposes it is set to the valid URL required by my app.

As stated in above answers , MockWebServer is a great library for mocking retrofit responses , but you don't need that library for mocking this exception . For mocking all other exceptions I would recommend MockWebServer , I use it a lot in my project for testing responses.

Note : You can set the app url to anything as long as that url doesn't exist on the web.

1

mockWebServer.shutdown() before executing your unit test is fine.

Internally it closes the socket connection:

serverSocket!!.close()
Michał Dobi Dobrzański
  • 1,449
  • 1
  • 20
  • 19