简体   繁体   English

Robolectric + OkHttp +改造+ rxJava单元测试

[英]Robolectric + OkHttp + retrofit + rxJava Unit Test

I'm trying to write a unit test for a piece of code with robolectric. 我正在尝试用robolectric编写一段代码的单元测试。 The problem is that I need to fake the http call but seems that robolectric's fake layer it works only with Apache's HttpClient as per this answer: 问题是我需要伪造http调用,但似乎robolectric的假层只适用于Apache的HttpClient,根据这个答案:

Link to answer 链接回答

In Retrofit you can't change the URL so the MockWebServer seems to be not an option. 在Retrofit中,您无法更改URL,因此MockWebServer似乎不是一个选项。

It seems that mockito can catch the retrofit callbacks but I'm using rxJava so I don't really know if it can helps. 似乎mockito可以捕获改进的回调,但我正在使用rxJava,所以我真的不知道它是否有帮助。

Does anyone has any suggestions about unit testing with Robolectric + Retrofit + okHttp + rxJava? 有没有人对Robolectric + Retrofit + okHttp + rxJava的单元测试有任何建议?

Here is a small piece of code: 这是一小段代码:

    @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();

  }

Robolectric.addPendingHttpResponse won't works anyway because of the OkHttp. 由于OkHttp,Robolectric.addPendingHttpResponse无论如何都不会起作用。 The api call is started when the button is pressed so in that I moment I need to fake the response! 按下按钮时启动api调用,因此我需要伪造响应!

You can get the server URL from a constant declared in the build.gradle and add a test flavor or buildType that overwrites it 您可以从build.gradle中声明的常量中获取服务器URL,并添加覆盖它的测试flavor或buildType

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

Another alternative not Android specific , ( less elegant IMHO but it works in all cases ) is to use a private variable that is only accessible and usable during testing, using reflection like this: 另一个不是Android特定的替代方案不太优雅的恕我直言,但它适用于所有情况 )是使用一个只在测试期间可访问和使用的私有变量,使用这样的反射:

  1. Create a private static variable that is null, ie private static String BASE_URL = null; 创建一个null的私有静态变量,即私有静态String BASE_URL = null;
  2. Use a method to get the host URL and in that method check whether to use BASE_URL when it's not null (never in the release version) or the URL from the resources (never hard-code the URL in the code) 使用方法获取主机URL,并在该方法中检查当它不为空时(从不在发布版本中)或来自资源的URL(从不在代码中对URL进行硬编码)时是否使用BASE_URL
  3. During testing use reflection to change the private visibility to public and modify the BASE_URL to your testing URL. 在测试期间,使用反射将私有可见性更改为public,并将BASE_URL修改为测试URL。

To do the reflection part use this example: 要执行反射部分,请使用以下示例:

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

Why can't you change the url in retrofit? 为什么不能在改造中更改网址?

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

You can set that url from MockWebServer: 您可以从MockWebServer设置该URL:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM