用Robolectric模拟HttpResponse

时间:2014-02-12 17:24:54

标签: android robolectric mockwebserver

使用Robolectric 2.3-SNAPSHOT,我想测试一个在后台执行请求的对象。为了隔离它,我试图模仿返回的HttpResponse,在投入几个小时后没有成功。

我创建了一个任何人都可以克隆的项目。模拟运行 ./ gradlew check https://github.com/Maragues/RobolectricDummyProject(git clone https://github.com/Maragues/RobolectricDummyProject.git

我试过

但测试失败是因为他们查询了真实的网址

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

可能相关的问题

3 个答案:

答案 0 :(得分:4)

您正在禁用Roboelectric的HTTP层,因此您正在使用真正的HTTP层。这意味着在你的测试中没有聪明的魔法发生:当你发送一个HTTP请求时,它真的会上网(正如你所看到的那样)。

MockWebServer不会停止此操作。它只是在本地设置一个Web服务器,您的测试可以连接到该服务器。

因此,要解决此问题,您需要停止尝试连接到真实服务器,而是连接到模拟服务器。为此,您需要在请求中注入/设置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();
  }

答案 1 :(得分:1)

事实证明,Robolectric的FakeHttpLayer仅适用于Apache的HttpClient,这对于大于Froyo的版本非常不鼓励。摘自Robolectric's Google Group

话虽如此,HttpUrlConnection的使用会给你带来麻烦。我尽可能尝试使用Android的HttpClient实现,因为Robolectric拦截了对该库的所有调用,并允许您设置对HTTP调用的预设响应。我们正在考虑为HttpUrlConnection做同样的事情,虽然目前还不清楚何时会发生这种情况。

除此之外,单元测试不需要模拟HTTP层。我的方法从一开始就错了。

答案 2 :(得分:1)

你可以试试这个(参考: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("/"));

然后,您可以将回复与server.enqueue(new MockResponse().setBody("it's all cool"));

进行比较

MockWebServer是okhttp https://github.com/square/okhttp/tree/master/mockwebserver的一部分。 android 4.4中的URLConnectionImpl已经changed from defaultHttpClient to Okhttp