11

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

可能相关的问题

4

3 回答 3

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();
  }
于 2014-02-24T00:24:42.287 回答
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已从 defaultHttpClient 更改为 Okhttp

于 2014-05-27T17:44:48.893 回答
1

事实证明,Robolectric 的FakeHttpLayer仅适用于 Apache 的 HttpClient,在高于 Froyo 的版本上强烈建议不要使用它。摘自Robolectric 的 Google Group

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

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

于 2014-02-24T08:41:06.637 回答