7

I'm trying to write a unit test for a piece of code with 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:

Link to answer

In Retrofit you can't change the URL so the MockWebServer seems to be not an option.

It seems that mockito can catch the retrofit callbacks but I'm using rxJava so I don't really know if it can helps.

Does anyone has any suggestions about unit testing with 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. The api call is started when the button is pressed so in that I moment I need to fake the response!

Community
  • 1
  • 1
fedestylah
  • 169
  • 1
  • 10

2 Answers2

1

You can get the server URL from a constant declared in the build.gradle and add a test flavor or buildType that overwrites it

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:

  1. Create a private static variable that is null, i.e. private static 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)
  3. During testing use reflection to change the private visibility to public and modify the BASE_URL to your testing 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 );
Sebas LG
  • 1,715
  • 1
  • 18
  • 31
0

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 server = new MockWebServer();
URL url = server.getUrl("/");
mromer
  • 1,867
  • 1
  • 13
  • 18
  • I can't do that because the RestAdapter is part of the my extension of the application class. So in the setUp method I just generate the activity that also generate the Application and the application class contains the RestAdapter with the default url of my api service. I can add a public method to the application class let me change the RestAdapter after but that means add code only for test purpose and it's wrong! – fedestylah Aug 28 '14 at 21:11
  • Yes, it is wrong. We have always the same problem creating mocks. After to read a lot, a solution to create mocks is to create factories to inject dependencies. So you will change your code to create factories and not for test purposes (if you want to see it in that way :P) – mromer Aug 29 '14 at 07:55
  • but anyway you're doing some work that you wouldn't do!! :) I If I don't find a better approach I'll try your way. Do you have any link or example where is exaplained the factories approach? because I'm not that confidend with factories. thanks! – fedestylah Aug 29 '14 at 09:04