Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mock HttpResponse with Robolectric

Using Robolectric 2.3-SNAPSHOT, I want to test an object that'll execute a request in the background. In order to isolate it, I'm trying to mock the HttpResponse returned, without success after some hours invested.

I've created a project that anyone can clone. Simly run ./gradlew check https://github.com/Maragues/RobolectricDummyProject (git clone https://github.com/Maragues/RobolectricDummyProject.git)

I've tried

  • Robolectric.setDefaultHttpResponse(200, "my_mocked_word");

  • MockWebServer (https://code.google.com/p/mockwebserver/)

But the tests fail because they query the real URL

  private static final String MOCKED_WORD = "MOCKED";

  @Test
  public void mockedRequestUsingMockServer() throws Exception {
    mMockWebServer.enqueue(new MockResponse().setBody(MOCKED_WORD));
    mMockWebServer.play();

    Robolectric.getFakeHttpLayer().interceptHttpRequests(false);
    Robolectric.getFakeHttpLayer().interceptResponseContent(false);

    String result = request.loadDataFromNetwork();

    assertEquals(MOCKED_WORD, result);
  }

  @Test
  public void mockedRequestUsingRobolectric() throws Exception {
    Robolectric.setDefaultHttpResponse(200, MOCKED_WORD);

    String result = request.loadDataFromNetwork();

    assertEquals(MOCKED_WORD, result);
  }

The code executing the request

public String loadDataFromNetwork() throws Exception {
    // With Uri.Builder class we can build our url is a safe manner
    Uri.Builder uriBuilder = Uri.parse("http://robospice-sample.appspot.com/reverse").buildUpon();
    uriBuilder.appendQueryParameter("word", word);

    String url = uriBuilder.build().toString();

    HttpURLConnection urlConnection = (HttpURLConnection) new URL(url)
      .openConnection();
    String result = IOUtils.toString(urlConnection.getInputStream());
    urlConnection.disconnect();

    return result;
  }

Possibly related questions

  • Can't capture HTTP request with robolectric (I've tried that without success. Perhaps I'm missing something)
  • Anyone had success mocking HttpRequests with Robolectric? (I'm not using eclipse)
like image 447
Maragues Avatar asked Feb 12 '14 17:02

Maragues


2 Answers

You're disabling Roboelectric's HTTP layer, so you're using the real HTTP layer. This means that there's no clever magic happening under the hood of your test: when you send an HTTP request, it's really going out onto the internet (as you are seeing).

MockWebServer doesn't stop this. It just sets up a web server locally, that your test can connect to.

So to resolve this problem, you need to stop attempting to connect to a real server, and instead, connect to the mock server. To do this, yo need to inject/set the URL in the request.

@Test
  public void mockedRequestUsingMockServer() throws Exception {
    mMockWebServer = new MockWebServer();
    mMockWebServer.play();
    mMockWebServer.enqueue(new MockResponse().setResponseCode(200).setBody(MOCKED_WORD));

    request.myUrl = mMockWebServer.getUrl("/");

    String result = request.loadDataFromNetwork();

    assertEquals(MOCKED_WORD, result);
    mMockWebServer.shutdown();
  }
like image 183
Paul Hicks Avatar answered Oct 12 '22 12:10

Paul Hicks


You can try this(ref:https://github.com/square/okhttp/tree/master/mockwebserver).

  // Create a MockWebServer. These are lean enough that you can create a new
    // instance for every unit test.
    MockWebServer server = new MockWebServer();
    // Schedule some responses.
    server.enqueue(new MockResponse().setBody("it's all cool"));
    // Start the server.
    server.play();
    // Ask the server for its URL. You'll need this to make HTTP requests.
    //Http is my own http executor.
    Http.Response response = http.get(server.getUrl("/"));

then, you can compare the response to server.enqueue(new MockResponse().setBody("it's all cool"));

MockWebServer is a part of okhttp https://github.com/square/okhttp/tree/master/mockwebserver. the URLConnectionImpl in android 4.4 have been changed from defaultHttpClient to Okhttp.

like image 44
log1000 Avatar answered Oct 12 '22 10:10

log1000