package com.artemzin.qualitymatters.integration_tests.api;
import com.artemzin.qualitymatters.QualityMattersIntegrationRobolectricTestRunner;
import com.artemzin.qualitymatters.api.QualityMattersRestApi;
import com.artemzin.qualitymatters.api.entities.Item;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.IOException;
import java.util.List;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import retrofit2.adapter.rxjava.HttpException;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
/**
* Main purpose of Integration tests is to check that all layers of your app work correctly, for example:
* <ul>
* <li>Http layer</li>
* <li>REST layer</li>
* <li>Parsing/Serializing layer</li>
* <li>Execution layer (ie RxJava)</li>
* </ul>
*/
@RunWith(QualityMattersIntegrationRobolectricTestRunner.class)
public class QualityMattersRestApiIntegrationTest {
private MockWebServer mockWebServer;
private QualityMattersRestApi qualityMattersRestApi;
@Before
public void beforeEachTest() throws IOException {
mockWebServer = new MockWebServer();
mockWebServer.start();
// Change base url to the mocked
QualityMattersIntegrationRobolectricTestRunner.qualityMattersApp().applicationComponent().changeableBaseUrl().setBaseUrl(mockWebServer.url("").toString());
qualityMattersRestApi = QualityMattersIntegrationRobolectricTestRunner.qualityMattersApp().applicationComponent().qualityMattersApi();
}
@After
public void afterEachTest() throws IOException {
mockWebServer.shutdown();
}
@Test
public void items_shouldHandleCorrectResponse() {
mockWebServer.enqueue(new MockResponse().setBody("["
+ "{ \"id\": \"test_id_1\", \"image_preview_url\": \"https://url1\", \"title\": \"Test title 1\", \"short_description\": \"Short desc 1\"},"
+ "{ \"id\": \"test_id_2\", \"image_preview_url\": \"https://url2\", \"title\": \"Test title 2\", \"short_description\": \"Short desc 2\"},"
+ "{ \"id\": \"test_id_3\", \"image_preview_url\": \"https://url3\", \"title\": \"Test title 3\", \"short_description\": \"Short desc 3\"}"
+ "]"));
// Get items from the API
List<Item> items = qualityMattersRestApi.items().toBlocking().value();
assertThat(items).hasSize(3);
assertThat(items.get(0).id()).isEqualTo("test_id_1");
assertThat(items.get(0).imagePreviewUrl()).isEqualTo("https://url1");
assertThat(items.get(0).title()).isEqualTo("Test title 1");
assertThat(items.get(0).shortDescription()).isEqualTo("Short desc 1");
assertThat(items.get(1).id()).isEqualTo("test_id_2");
assertThat(items.get(1).imagePreviewUrl()).isEqualTo("https://url2");
assertThat(items.get(1).title()).isEqualTo("Test title 2");
assertThat(items.get(1).shortDescription()).isEqualTo("Short desc 2");
assertThat(items.get(2).id()).isEqualTo("test_id_3");
assertThat(items.get(2).imagePreviewUrl()).isEqualTo("https://url3");
assertThat(items.get(2).title()).isEqualTo("Test title 3");
assertThat(items.get(2).shortDescription()).isEqualTo("Short desc 3");
}
// Such tests assert that no matter how we implement our REST api:
// Retrofit or not
// OkHttp or not
// It should handle error responses too.
@Test
public void items_shouldThrowExceptionIfWebServerRespondError() {
for (Integer errorCode : HttpCodes.clientAndServerSideErrorCodes()) {
mockWebServer.enqueue(new MockResponse().setStatus("HTTP/1.1 " + errorCode + " Not today"));
try {
qualityMattersRestApi.items().toBlocking().value();
fail("HttpException should be thrown for error code: " + errorCode);
} catch (RuntimeException expected) {
HttpException httpException = (HttpException) expected.getCause();
assertThat(httpException.code()).isEqualTo(errorCode);
assertThat(httpException.message()).isEqualTo("Not today");
}
}
}
}