Search code examples
mockitoandroid-espressoandroid-testingandroid-instrumentationmockwebserver

How to mock two APIs with MockWebServer Android test cases


I am performing instrumentation testing, in that I am invoking one of the activities which call 2 APIs when activity is created.

Now I want to write instrumentation test cases for this activity, where I have to mock the API response with mockWebServer of mockito. My mocking code works fine when I call one single API, but it fails when two APIs are getting called simultaneously.

Even there is another scenario let's say, we have API to fetch recent message data, but before that, we always authenticate the user by sending refresh token. In such cases, we need to call API which authenticates the user and then another API to fetch message data. Hence we need to call 2 APIs one after another, let's say in a single method. How will I mock authentication API response and messages API response while writing test cases of that single method?

How should I deal with this issue? Is there any other approach to deal with such a situation where we need to call more than one API at the same time?

Also, I have used SystemClock.sleep(4000); as my callbacks were getting performed asynchronously.

Below is my code to mock API:

public class MyAPIActivityTest {

@Rule
public InstantTaskExecutorRule mInstantTaskExecutorRule = new InstantTaskExecutorRule();
@Rule
public ActivityTestRule<MyAPIActivity> myAPIActivityTestRule = new ActivityTestRule<>(MyAPIActivity.class, true, false);

MockWebServer mockWebServer;
@Before
public void setUp() {
    MockitoAnnotations.initMocks(this);
}

@Test
public void checkVisibilityOfTaskListMockedValidData() throws Exception {
    myAPIActivityTestRule.launchActivity(null);
    String fileName = "json_files/valid_api_response.json";
    mockWebServer = new MockWebServer();
    int PORT_NUMBER = 50205;
    mockWebServer.start(PORT_NUMBER);
    ApiUrls.BASE_QUERY_URL = mockWebServer.url("/").toString();
    mockWebServer.enqueue(new MockResponse()
            .setBody(getStringFromFile(getContext(), fileName)));

    SystemClock.sleep(4000);

    Assert.assertEquals(View.VISIBLE, myAPIActivityTestRule.IvDataIsPresent.getVisibility());
    Assert.assertEquals(View.GONE, myAPIActivityTestRule.IvDataNotPresent.getVisibility());
}

@After
public void tearDown() throws Exception {
    mockWebServer.shutdown();
}


public static String convertStreamToString(InputStream inputStream) throws Exception {
    BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
    StringBuilder stringBuilder = new StringBuilder();
    String line;
    while ((line = reader.readLine()) != null) {
        stringBuilder.append(line).append(StringCharacters.NEW_LINE);
    }
    reader.close();
    return stringBuilder.toString();
}

public static String getStringFromFile(Context context, String filePath) throws Exception {
    final InputStream stream = context.getResources().getAssets().open(filePath);

    String text = convertStreamToString(stream);
    stream.close();
    return text;
}
}

Any help is appreciated. Thanks in advance.


Solution

  • After an investigation, I have found the solutions. Hence replying to my question.

    1. The Dispatcher helps to add more than 1 mocked response
    2. Idling Resources & Awaitility library will help to avoid adding sleep time i.e., SystemClock.sleep(4000).

    For more details, below blog might help:

    https://blog.kiprosh.com/how-to-test-api-response-with-mockwebserver-library/