用Robolectric模拟HttpResponse

Mar*_*ues 11 android robolectric mockwebserver

使用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);
  }
Run Code Online (Sandbox Code Playgroud)

执行请求的代码

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;
  }
Run Code Online (Sandbox Code Playgroud)

可能相关的问题

Pau*_*cks 5

您将禁用 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();
  }
Run Code Online (Sandbox Code Playgroud)


Mar*_*ues 2

事实证明,Robolectric 的FakeHttpLayer只能与 Apache 的 HttpClient 配合使用,在高于 Froyo 的版本上强烈建议不要这样做。摘自Robolectric 的 Google 群组

话虽这么说,使用 HttpUrlConnection 会给你带来麻烦。我会尽可能使用 Android 的 HttpClient 实现,因为 Robolectric 会拦截对该库的所有调用,并允许您设置对 HTTP 调用的预设响应。我们正在考虑对 HttpUrlConnection 执行相同的操作,但尚不清楚何时会发生。

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

  • 为什么单元测试不应该模拟 http 层,它是一个外部依赖项,可能会引入一些未知和闪烁的结果,否则您将如何确保特定结果? (2认同)