Mock server requests Android Espresso UI Testing

5.5k views Asked by At

I am using Espresso to write UI tests for my Android application and would like to mock http requests using MockWebServer. I need to mock authentication responses and sign in the user before the tests are run.

Is there a way make the app use mockwebserver so that isntead of making actual requests, I can use respontes enqueued on mockwebserver.

So far I have:

public class AuthenticationTest {

@Rule
public ActivityTestRule<Authentication> mActivityTestRule = new ActivityTestRule<>(Authentication.class);

private  Authentication activity;
private MockWebServer server;

@Before
public void signin() throws Exception {
    server = new MockWebServer();
    server.start();
    activity = mActivityTestRule.getActivity();
    MyApplication.State state = activity.getState();

    String serverUrl = server.url("/").toString();

    // Here is where I have a problem. How to force client to use mock server?

}

@Test
public void firstTest() {
    String contentType = "Content-type: application/json";
    MockResponse r1 = new MockResponse().setResponseCode(200).setBody("example_body").addHeader(contentType);
    server.enqueue(r1);

    // typing credentials and pressing "Sign in" button, which should use mocked server's response:

    ViewInteraction email = onView(allOf(withId(R.id.emailAddress), isDisplayed()));
    email.perform(replaceText("[email protected]"), closeSoftKeyboard());
    ViewInteraction password = onView(allOf(withId(R.id.password), isDisplayed()));
    password.perform(replaceText("some_password"), closeSoftKeyboard());
    ViewInteraction signin = onView(allOf(withId(R.id.signInButton), withText("Sign In"), isDisplayed()));
    button2.perform(click());
}
1

There are 1 answers

0
LethalMaus On

A little late to the party but in case some reference is needed. You have to configure your client to communicate with the MockWebServer. The MockWebServer listens on localhost aka. loopback address, where as the client is most likely in your case configured to communicate with the original API url.

The cleanest way (IMO) to achieve this is to create a build variant or flavour that where each build contains a different xml file that states the url. This way you can have a 'mock' build that communicates with localhost, and every other build with the original API url.

If you need an example, you can have a look here. Under /app/src/mock/res/values/environment.xml you will see the following resources

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name" translatable="false">ExampleAndroidProject</string>
    <string name="imdb_base_url" translatable="false">http://127.0.0.1:8185</string>
    <string name="imdb_api_key" translatable="false">imdb_api_key</string>
</resources>