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.