【问题标题】:Robolectric + OkHttp + retrofit + rxJava Unit TestRobolectric + OkHttp + 改造 + rxJava 单元测试
【发布时间】:2014-10-22 12:13:15
【问题描述】:

我正在尝试使用 robolectric 为一段代码编写单元测试。问题是我需要伪造 http 调用,但似乎 robolectric 的假层只适用于 Apache 的 HttpClient 根据这个答案:

Link to answer

在 Retrofit 中,您无法更改 URL,因此 MockWebServer 似乎不是一个选项。

mockito 似乎可以捕获改造回调,但我使用的是 rxJava,所以我真的不知道它是否有帮助。

有人对使用 Robolectric + Retrofit + okHttp + rxJava 进行单元测试有什么建议吗?

这是一小段代码:

    @Test
public void test1() throws IOException, InterruptedException {
    FragmentA frag = (FragmentA) activity
            .getFragmentManager().findFragmentById(
                    R.id.frag);
    assertThat(frag).isNotNull();
    assertThat(frag.isVisible()).isTrue();

    EditText input1 = (EditText) frag.getView()
            .findViewById(R.id.edit_text1);
    EditText input2 = (EditText) frag.getView()
            .findViewById(R.id.edit_text2);
    Button button = (button) frag.getView()
            .findViewById(R.id.button);
    input1.setText("999");
    input2.setText("999");
    Robolectric.addPendingHttpResponse(200, "{\"isValid\": true}");
    button.performClick();
            assertThat(
            ShadowAlertDialog.getLatestDialog() instanceof ProgressDialog)
            .isTrue();

  }

由于 OkHttp,Robolectric.addPendingHttpResponse 无论如何都不会工作。按下按钮时会启动 api 调用,因此我需要伪造响应!

【问题讨论】:

    标签: android unit-testing robolectric retrofit rx-java


    【解决方案1】:

    您可以从 build.gradle 中声明的常量获取服务器 URL,并添加覆盖它的测试风格或 buildType

    release {
        buildConfigField "String", "SERVER_URL", "\"github.com\""
    }
    testing {
        buildConfigField "String", "SERVER_URL", "\"127.0.0.1\""
    }
    

    另一个不是 Android 特定的替代方案,(恕我直言不那么优雅,但它适用于所有情况)是使用一个私有变量,该变量只能在测试期间访问和使用,使用像这样的反射:

    1. 创建一个为null的私有静态变量,即private static String BASE_URL = null;
    2. 使用一种方法获取主机 URL,并在该方法中检查是否使用 BASE_URL 不为空(从不在发布版本中)或来自资源的 URL(从不在代码中硬编码 URL)李>
    3. 在测试期间,使用反射将私有可见性更改为公开,并将 BASE_URL 修改为您的测试 URL。

    要进行反射部分,请使用以下示例:

    final Field urlField = MyService.class.getDeclaredField("BASE_URL");
    urlField.setAccessible(true);
    urlField.set(null, TEST_URL );
    

    【讨论】:

      【解决方案2】:

      为什么你不能在改造中更改网址?

      RestAdapter restAdapter = new RestAdapter.Builder()
          .setEndpoint("https://api.github.com")
          .build();
      

      您可以从 MockWebServer 设置该网址:

      MockWebServer server = new MockWebServer();
      URL url = server.getUrl("/");
      

      【讨论】:

      • 我不能这样做,因为 RestAdapter 是我的应用程序类扩展的一部分。因此,在 setUp 方法中,我只生成也生成应用程序的活动,并且应用程序类包含 RestAdapter 和我的 api 服务的默认 url。我可以向应用程序类添加一个公共方法,让我在之后更改 RestAdapter 但这意味着添加代码仅用于测试目的,这是错误的!
      • 是的,这是错误的。我们在创建模拟时总是遇到同样的问题。看了很多之后,创建mock的一个解决方案是创建工厂注入依赖。因此,您将更改代码以创建工厂而不是出于测试目的(如果您想以这种方式查看它:P)
      • 但无论如何你正在做一些你不会做的工作!! :) 我如果找不到更好的方法,我会尝试你的方法。您是否有任何链接或示例可以解释工厂方法?因为我对工厂没那么自信。谢谢!
      猜你喜欢
      • 2016-10-20
      • 2020-09-05
      • 2019-02-19
      • 2015-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多