Mock HttpResponse с Robolectric

Используя Robolectric 2.3-SNAPSHOT, я хочу протестировать объект, который выполнит запрос в фоновом режиме. Чтобы изолировать его, я пытаюсь высмеять возвращаемый HttpResponse без успеха через несколько часов.

Я создал проект, который любой может клонировать. Просто выполните. /gradlew проверьте https://github.com/Maragues/RobolectricDummyProject (git clone https://github.com/Maragues/RobolectricDummyProject.git)

Я пробовал

Но тесты терпят неудачу, потому что они запрашивают реальный 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);
  }

Код, выполняющий запрос

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;
  }

Возможно, связанные вопросы

Ответ 1

Оказывается, Robolectric FakeHttpLayer работает только с Apache HttpClient, который сильно обескуражен версиями, большими, чем Froyo. Извлечен из Robolectric Google Group

При этом использование HttpUrlConnection вызовет у вас проблемы. Я бы попытался использовать реализацию HttpClient в Android, где это возможно, поскольку Robolectric перехватывает все вызовы в эту библиотеку и позволяет настраивать ответы на ваши HTTP-вызовы. Мы смотрим на то же самое для HttpUrlConnection, хотя это неясно, когда это произойдет.

Кроме того, unit test не нужно издеваться над уровнем HTTP. Мой подход был неправильным с самого начала.

Ответ 2

Вы отключите Roboelectric HTTP-уровень, поэтому используете настоящий HTTP-уровень. Это означает, что при капоте вашего теста нет умной магии: когда вы отправляете HTTP-запрос, он действительно выходит в Интернет (как вы видите).

MockWebServer не останавливает это. Он просто настраивает веб-сервер локально, к которому может подключиться ваш тест.

Итак, чтобы решить эту проблему, вам нужно прекратить попытки подключиться к реальному серверу, а вместо этого подключиться к макету сервера. Для этого вам нужно ввести/установить URL-адрес в запросе.

@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();
  }

Ответ 3

Вы можете попробовать это (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 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("/"));

тогда вы можете сравнить ответ с server.enqueue(new MockResponse().setBody("it all cool"));

MockWebServer является частью okhttp https://github.com/square/okhttp/tree/master/mockwebserver. URLConnectionImpl в android 4.4 был изменен с defaultHttpClient на Okhttp.