├── .gitignore ├── LICENSE ├── README.md └── RetrofitTestExample ├── .gitignore ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ ├── assets │ │ ├── quote_200_ok_response.json │ │ └── quote_404_not_found.json │ └── java │ │ └── za │ │ └── co │ │ └── riggaroo │ │ └── retrofittestexample │ │ ├── MainActivityTest.java │ │ ├── MockFailedQODService.java │ │ ├── MockQuoteOfTheDayService.java │ │ ├── QuoteOfTheDayMockAdapterTest.java │ │ └── RestServiceTestHelper.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── za │ │ │ └── co │ │ │ └── riggaroo │ │ │ └── retrofittestexample │ │ │ ├── MainActivity.java │ │ │ ├── QuoteOfTheDayConstants.java │ │ │ ├── QuoteOfTheDayRestService.java │ │ │ ├── interceptor │ │ │ └── LoggingInterceptor.java │ │ │ └── pojo │ │ │ ├── Contents.java │ │ │ ├── Error.java │ │ │ ├── Quote.java │ │ │ ├── QuoteOfTheDayErrorResponse.java │ │ │ ├── QuoteOfTheDayResponse.java │ │ │ └── Success.java │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── za │ └── co │ └── riggaroo │ └── retrofittestexample │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | 15 | # Gradle files 16 | .gradle/ 17 | build/ 18 | /*/build/ 19 | 20 | # Local configuration file (sdk path, etc) 21 | local.properties 22 | 23 | # Proguard folder generated by Eclipse 24 | proguard/ 25 | 26 | # Log Files 27 | *.log 28 | 29 | RetrofitTestExample/.idea/.name 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Rebecca Franks 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # android-retrofit-test-examples 2 | Example usage for testing different server responses from an API. This is using Retrofit 2, Retrofit Mock Webservers and Espresso. 3 | 4 | Check out the blog post http://wp.me/p6bCW9-4d 5 | -------------------------------------------------------------------------------- /RetrofitTestExample/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | /.idea 4 | .DS_Store 5 | /build 6 | /captures 7 | *.iml 8 | -------------------------------------------------------------------------------- /RetrofitTestExample/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /RetrofitTestExample/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.1" 6 | 7 | defaultConfig { 8 | applicationId "za.co.riggaroo.retrofittestexample" 9 | minSdkVersion 15 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "1.0" 13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 14 | 15 | } 16 | buildTypes { 17 | release { 18 | minifyEnabled false 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | packagingOptions { 23 | exclude 'META-INF/LICENSE' 24 | exclude 'META-INF/NOTICE' 25 | } 26 | 27 | } 28 | 29 | dependencies { 30 | compile fileTree(dir: 'libs', include: ['*.jar']) 31 | testCompile 'junit:junit:4.12' 32 | compile 'com.android.support:appcompat-v7:23.0.1' 33 | compile 'com.squareup.retrofit2:retrofit:2.0.0' 34 | compile 'com.squareup.retrofit2:converter-jackson:2.0.0' 35 | compile 'com.squareup.okhttp:okhttp:2.7.0' 36 | androidTestCompile 'com.squareup.retrofit2:retrofit-mock:2.0.0' 37 | androidTestCompile ('com.squareup.okhttp:mockwebserver:2.7.0') 38 | androidTestCompile 'com.android.support.test:runner:0.4' 39 | androidTestCompile 'com.android.support.test:rules:0.4' 40 | androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1' 41 | androidTestCompile 'com.squareup.spoon:spoon-client:1.2.0' 42 | } 43 | -------------------------------------------------------------------------------- /RetrofitTestExample/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/rebeccafranks/Library/Android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /RetrofitTestExample/app/src/androidTest/assets/quote_200_ok_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "success": { 3 | "total": 1 4 | }, 5 | "contents": { 6 | "quotes": [ 7 | { 8 | "quote": "I came from a real tough neighborhood. Once a guy pulled a knife on me. I knew he wasn't a professional, the knife had butter on it.", 9 | "length": "132", 10 | "author": "Rodney Dangerfield", 11 | "tags": [ 12 | "funny", 13 | "humor" 14 | ], 15 | "category": "funny", 16 | "id": "3e_ZsKxPKu5SuuAa6Pa_0AeF" 17 | } 18 | ] 19 | } 20 | } -------------------------------------------------------------------------------- /RetrofitTestExample/app/src/androidTest/assets/quote_404_not_found.json: -------------------------------------------------------------------------------- 1 | { 2 | "error": { 3 | "code": 404, 4 | "message": "Quote Not found" 5 | } 6 | } -------------------------------------------------------------------------------- /RetrofitTestExample/app/src/androidTest/java/za/co/riggaroo/retrofittestexample/MainActivityTest.java: -------------------------------------------------------------------------------- 1 | package za.co.riggaroo.retrofittestexample; 2 | 3 | import android.content.Intent; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.espresso.matcher.ViewMatchers; 6 | import android.support.test.rule.ActivityTestRule; 7 | import android.support.test.runner.AndroidJUnit4; 8 | import android.test.InstrumentationTestCase; 9 | import com.squareup.okhttp.mockwebserver.MockResponse; 10 | import com.squareup.okhttp.mockwebserver.MockWebServer; 11 | 12 | import org.junit.After; 13 | import org.junit.Before; 14 | import org.junit.Rule; 15 | import org.junit.Test; 16 | import org.junit.runner.RunWith; 17 | 18 | import static android.support.test.espresso.Espresso.onView; 19 | import static android.support.test.espresso.assertion.ViewAssertions.*; 20 | import static android.support.test.espresso.matcher.ViewMatchers.*; 21 | import static android.support.test.espresso.matcher.ViewMatchers.withId; 22 | import static android.support.test.espresso.matcher.ViewMatchers.withText; 23 | 24 | /** 25 | * @author rebeccafranks 26 | * @since 15/10/25. 27 | */ 28 | @RunWith(AndroidJUnit4.class) 29 | public class MainActivityTest extends InstrumentationTestCase { 30 | 31 | 32 | @Rule 33 | public ActivityTestRule mActivityRule = 34 | new ActivityTestRule<>(MainActivity.class, true, false); 35 | private MockWebServer server; 36 | 37 | @Before 38 | public void setUp() throws Exception { 39 | super.setUp(); 40 | server = new MockWebServer(); 41 | server.start(); 42 | injectInstrumentation(InstrumentationRegistry.getInstrumentation()); 43 | QuoteOfTheDayConstants.BASE_URL = server.url("/").toString(); 44 | } 45 | 46 | @Test 47 | public void testQuoteIsShown() throws Exception { 48 | String fileName = "quote_200_ok_response.json"; 49 | server.enqueue(new MockResponse() 50 | .setResponseCode(200) 51 | .setBody(RestServiceTestHelper.getStringFromFile(getInstrumentation().getContext(), fileName))); 52 | 53 | Intent intent = new Intent(); 54 | mActivityRule.launchActivity(intent); 55 | 56 | onView(withId(R.id.button_retry)).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE))); 57 | onView(withText("I came from a real tough neighborhood. Once a guy pulled a knife on me. I knew he wasn't a professional, the knife had butter on it.")).check(matches(isDisplayed())); 58 | } 59 | 60 | 61 | @Test 62 | public void testRetryButtonShowsWhenError() throws Exception { 63 | String fileName = "quote_404_not_found.json"; 64 | 65 | server.enqueue(new MockResponse() 66 | .setResponseCode(404) 67 | .setBody(RestServiceTestHelper.getStringFromFile(getInstrumentation().getContext(), fileName))); 68 | 69 | Intent intent = new Intent(); 70 | mActivityRule.launchActivity(intent); 71 | 72 | onView(withId(R.id.button_retry)).check(matches(isDisplayed())); 73 | onView(withText("Quote Not found")).check(matches(isDisplayed())); 74 | } 75 | 76 | @After 77 | public void tearDown() throws Exception { 78 | server.shutdown(); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /RetrofitTestExample/app/src/androidTest/java/za/co/riggaroo/retrofittestexample/MockFailedQODService.java: -------------------------------------------------------------------------------- 1 | package za.co.riggaroo.retrofittestexample; 2 | 3 | import android.util.Log; 4 | 5 | import com.fasterxml.jackson.core.JsonProcessingException; 6 | import com.fasterxml.jackson.databind.ObjectMapper; 7 | import com.fasterxml.jackson.databind.ObjectWriter; 8 | 9 | import java.io.IOException; 10 | 11 | import okhttp3.MediaType; 12 | import okhttp3.ResponseBody; 13 | import retrofit2.Call; 14 | import retrofit2.Response; 15 | import retrofit2.Retrofit; 16 | import retrofit2.mock.Calls; 17 | import za.co.riggaroo.retrofittestexample.pojo.Error; 18 | import za.co.riggaroo.retrofittestexample.pojo.QuoteOfTheDayErrorResponse; 19 | import za.co.riggaroo.retrofittestexample.pojo.QuoteOfTheDayResponse; 20 | 21 | import retrofit2.mock.BehaviorDelegate; 22 | /** 23 | * @author rebeccafranks 24 | * @since 15/10/25. 25 | */ 26 | public class MockFailedQODService implements QuoteOfTheDayRestService { 27 | private static final String TAG = "MockFailedQOD"; 28 | private final BehaviorDelegate delegate; 29 | 30 | public MockFailedQODService(BehaviorDelegate restServiceBehaviorDelegate) { 31 | this.delegate = restServiceBehaviorDelegate; 32 | 33 | } 34 | 35 | @Override 36 | public Call getQuoteOfTheDay() { 37 | za.co.riggaroo.retrofittestexample.pojo.Error error = new Error(); 38 | error.setCode(404); 39 | error.setMessage("Quote Not Found"); 40 | QuoteOfTheDayErrorResponse quoteOfTheDayErrorResponse = new QuoteOfTheDayErrorResponse(); 41 | quoteOfTheDayErrorResponse.setError(error); 42 | 43 | ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter(); 44 | String json = ""; 45 | try { 46 | json = ow.writeValueAsString(quoteOfTheDayErrorResponse); 47 | Response response = Response.error(404, ResponseBody.create(MediaType.parse("application/json") ,json)); 48 | return delegate.returning(Calls.response(response)).getQuoteOfTheDay(); 49 | // return delegate.returningResponse(response).getQuoteOfTheDay(); 50 | } catch (JsonProcessingException e) { 51 | Log.e(TAG, "JSON Processing exception:",e); 52 | return Calls.failure(e); 53 | } 54 | 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /RetrofitTestExample/app/src/androidTest/java/za/co/riggaroo/retrofittestexample/MockQuoteOfTheDayService.java: -------------------------------------------------------------------------------- 1 | package za.co.riggaroo.retrofittestexample; 2 | 3 | import java.util.ArrayList; 4 | 5 | import retrofit2.Call; 6 | import retrofit2.Response; 7 | import retrofit2.mock.BehaviorDelegate; 8 | import za.co.riggaroo.retrofittestexample.pojo.Contents; 9 | import za.co.riggaroo.retrofittestexample.pojo.Quote; 10 | import za.co.riggaroo.retrofittestexample.pojo.QuoteOfTheDayResponse; 11 | 12 | /** 13 | * @author rebeccafranks 14 | * @since 15/10/24. 15 | */ 16 | public class MockQuoteOfTheDayService implements QuoteOfTheDayRestService { 17 | 18 | private final BehaviorDelegate delegate; 19 | 20 | public MockQuoteOfTheDayService(BehaviorDelegate service) { 21 | this.delegate = service; 22 | } 23 | 24 | @Override 25 | public Call getQuoteOfTheDay() { 26 | QuoteOfTheDayResponse quoteOfTheDayResponse = new QuoteOfTheDayResponse(); 27 | Contents contents = new Contents(); 28 | Quote quote = new Quote(); 29 | quote.setQuote("Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live."); 30 | ArrayList quotes = new ArrayList<>(); 31 | quotes.add(quote); 32 | contents.setQuotes(quotes); 33 | quoteOfTheDayResponse.setContents(contents); 34 | return delegate.returningResponse(quoteOfTheDayResponse).getQuoteOfTheDay(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /RetrofitTestExample/app/src/androidTest/java/za/co/riggaroo/retrofittestexample/QuoteOfTheDayMockAdapterTest.java: -------------------------------------------------------------------------------- 1 | package za.co.riggaroo.retrofittestexample; 2 | 3 | import android.test.InstrumentationTestCase; 4 | import android.test.suitebuilder.annotation.SmallTest; 5 | 6 | 7 | import junit.framework.Assert; 8 | 9 | import java.lang.annotation.Annotation; 10 | import okhttp3.OkHttpClient; 11 | import okhttp3.ResponseBody; 12 | import retrofit2.Call; 13 | import retrofit2.Converter; 14 | import retrofit2.Response; 15 | import retrofit2.Retrofit; 16 | import retrofit2.converter.jackson.JacksonConverterFactory; 17 | import retrofit2.mock.BehaviorDelegate; 18 | import retrofit2.mock.MockRetrofit; 19 | import retrofit2.mock.NetworkBehavior; 20 | import za.co.riggaroo.retrofittestexample.pojo.QuoteOfTheDayErrorResponse; 21 | import za.co.riggaroo.retrofittestexample.pojo.QuoteOfTheDayResponse; 22 | 23 | /** 24 | * @author rebeccafranks 25 | * @since 15/10/23. 26 | */ 27 | public class QuoteOfTheDayMockAdapterTest extends InstrumentationTestCase { 28 | private MockRetrofit mockRetrofit; 29 | private Retrofit retrofit; 30 | 31 | @Override 32 | public void setUp() throws Exception { 33 | super.setUp(); 34 | retrofit = new Retrofit.Builder().baseUrl("http://test.com") 35 | .client(new OkHttpClient()) 36 | .addConverterFactory(JacksonConverterFactory.create()) 37 | .build(); 38 | 39 | NetworkBehavior behavior = NetworkBehavior.create(); 40 | 41 | mockRetrofit = new MockRetrofit.Builder(retrofit) 42 | .networkBehavior(behavior) 43 | .build(); 44 | } 45 | 46 | 47 | @SmallTest 48 | public void testRandomQuoteRetrieval() throws Exception { 49 | BehaviorDelegate delegate = mockRetrofit.create(QuoteOfTheDayRestService.class); 50 | QuoteOfTheDayRestService mockQodService = new MockQuoteOfTheDayService(delegate); 51 | 52 | 53 | //Actual Test 54 | Call quote = mockQodService.getQuoteOfTheDay(); 55 | Response quoteOfTheDayResponse = quote.execute(); 56 | 57 | //Asserting response 58 | Assert.assertTrue(quoteOfTheDayResponse.isSuccessful()); 59 | Assert.assertEquals("Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.", quoteOfTheDayResponse.body().getContents().getQuotes().get(0).getQuote()); 60 | 61 | } 62 | 63 | @SmallTest 64 | public void testFailedQuoteRetrieval() throws Exception { 65 | BehaviorDelegate delegate = mockRetrofit.create(QuoteOfTheDayRestService.class); 66 | MockFailedQODService mockQodService = new MockFailedQODService(delegate); 67 | 68 | //Actual Test 69 | Call quote = mockQodService.getQuoteOfTheDay(); 70 | Response quoteOfTheDayResponse = quote.execute(); 71 | Assert.assertFalse(quoteOfTheDayResponse.isSuccessful()); 72 | 73 | Converter errorConverter = retrofit.responseBodyConverter(QuoteOfTheDayErrorResponse.class, new Annotation[0]); 74 | QuoteOfTheDayErrorResponse error = errorConverter.convert(quoteOfTheDayResponse.errorBody()); 75 | 76 | //Asserting response 77 | Assert.assertEquals(404, quoteOfTheDayResponse.code()); 78 | Assert.assertEquals("Quote Not Found", error.getError().getMessage()); 79 | 80 | } 81 | } -------------------------------------------------------------------------------- /RetrofitTestExample/app/src/androidTest/java/za/co/riggaroo/retrofittestexample/RestServiceTestHelper.java: -------------------------------------------------------------------------------- 1 | package za.co.riggaroo.retrofittestexample; 2 | 3 | import android.content.Context; 4 | 5 | import java.io.BufferedReader; 6 | import java.io.InputStream; 7 | import java.io.InputStreamReader; 8 | 9 | /** 10 | * @author rebeccafranks 11 | * @since 15/10/24. 12 | */ 13 | public class RestServiceTestHelper { 14 | 15 | public static String convertStreamToString(InputStream is) throws Exception { 16 | BufferedReader reader = new BufferedReader(new InputStreamReader(is)); 17 | StringBuilder sb = new StringBuilder(); 18 | String line; 19 | while ((line = reader.readLine()) != null) { 20 | sb.append(line).append("\n"); 21 | } 22 | reader.close(); 23 | return sb.toString(); 24 | } 25 | 26 | public static String getStringFromFile(Context context, String filePath) throws Exception { 27 | final InputStream stream = context.getResources().getAssets().open(filePath); 28 | 29 | String ret = convertStreamToString(stream); 30 | //Make sure you close all streams. 31 | stream.close(); 32 | return ret; 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /RetrofitTestExample/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /RetrofitTestExample/app/src/main/java/za/co/riggaroo/retrofittestexample/MainActivity.java: -------------------------------------------------------------------------------- 1 | package za.co.riggaroo.retrofittestexample; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.util.Log; 6 | import android.view.View; 7 | import android.widget.Button; 8 | import android.widget.TextView; 9 | 10 | 11 | import java.io.IOException; 12 | import java.lang.annotation.Annotation; 13 | 14 | import okhttp3.OkHttpClient; 15 | import okhttp3.ResponseBody; 16 | import retrofit2.Call; 17 | import retrofit2.Callback; 18 | import retrofit2.Converter; 19 | import retrofit2.Response; 20 | import retrofit2.Retrofit; 21 | import retrofit2.converter.jackson.JacksonConverterFactory; 22 | import za.co.riggaroo.retrofittestexample.interceptor.LoggingInterceptor; 23 | import za.co.riggaroo.retrofittestexample.pojo.QuoteOfTheDayErrorResponse; 24 | import za.co.riggaroo.retrofittestexample.pojo.QuoteOfTheDayResponse; 25 | 26 | public class MainActivity extends AppCompatActivity { 27 | 28 | private TextView textViewQuoteOfTheDay; 29 | private Button buttonRetry; 30 | 31 | private static final String TAG = "MainActivity"; 32 | private QuoteOfTheDayRestService service; 33 | private Retrofit retrofit; 34 | 35 | @Override 36 | protected void onCreate(Bundle savedInstanceState) { 37 | super.onCreate(savedInstanceState); 38 | setContentView(R.layout.activity_main); 39 | 40 | textViewQuoteOfTheDay = (TextView) findViewById(R.id.text_view_quote); 41 | buttonRetry = (Button) findViewById(R.id.button_retry); 42 | buttonRetry.setOnClickListener(new View.OnClickListener() { 43 | @Override 44 | public void onClick(View v) { 45 | getQuoteOfTheDay(); 46 | } 47 | }); 48 | 49 | OkHttpClient client = new OkHttpClient(); 50 | // client.interceptors().add(new LoggingInterceptor()); 51 | retrofit = new Retrofit.Builder() 52 | .baseUrl(QuoteOfTheDayConstants.BASE_URL) 53 | .addConverterFactory(JacksonConverterFactory.create()) 54 | .client(client) 55 | .build(); 56 | service = retrofit.create(QuoteOfTheDayRestService.class); 57 | getQuoteOfTheDay(); 58 | 59 | } 60 | 61 | 62 | private void getQuoteOfTheDay() { 63 | Call call = 64 | service.getQuoteOfTheDay(); 65 | 66 | call.enqueue(new Callback() { 67 | 68 | @Override 69 | public void onResponse(Call call, Response response) { 70 | if (response.isSuccessful()) { 71 | textViewQuoteOfTheDay.setText(response.body().getContents().getQuotes().get(0).getQuote()); 72 | } else { 73 | try { 74 | Converter errorConverter = retrofit.responseBodyConverter(QuoteOfTheDayErrorResponse.class, new Annotation[0]); 75 | QuoteOfTheDayErrorResponse error = errorConverter.convert(response.errorBody()); 76 | showRetry(error.getError().getMessage()); 77 | 78 | } catch (IOException e) { 79 | Log.e(TAG, "IOException parsing error:", e); 80 | } 81 | 82 | } 83 | } 84 | 85 | @Override 86 | public void onFailure(Call call, Throwable t) { 87 | //Transport level errors such as no internet etc. 88 | } 89 | }); 90 | 91 | 92 | } 93 | 94 | private void showRetry(String error) { 95 | textViewQuoteOfTheDay.setText(error); 96 | buttonRetry.setVisibility(View.VISIBLE); 97 | 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /RetrofitTestExample/app/src/main/java/za/co/riggaroo/retrofittestexample/QuoteOfTheDayConstants.java: -------------------------------------------------------------------------------- 1 | package za.co.riggaroo.retrofittestexample; 2 | 3 | import android.app.Application; 4 | 5 | /** 6 | * @author rebeccafranks 7 | * @since 15/10/25. 8 | */ 9 | public class QuoteOfTheDayConstants { 10 | 11 | public static String BASE_URL = "http://api.theysaidso.com"; 12 | 13 | 14 | } 15 | -------------------------------------------------------------------------------- /RetrofitTestExample/app/src/main/java/za/co/riggaroo/retrofittestexample/QuoteOfTheDayRestService.java: -------------------------------------------------------------------------------- 1 | package za.co.riggaroo.retrofittestexample; 2 | 3 | import retrofit2.Call; 4 | import retrofit2.Response; 5 | import retrofit2.http.GET; 6 | import za.co.riggaroo.retrofittestexample.pojo.QuoteOfTheDayResponse; 7 | 8 | /** 9 | * @author rebeccafranks 10 | * @since 15/10/23. 11 | */ 12 | public interface QuoteOfTheDayRestService { 13 | 14 | @GET("/qod.json") 15 | Call getQuoteOfTheDay(); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /RetrofitTestExample/app/src/main/java/za/co/riggaroo/retrofittestexample/interceptor/LoggingInterceptor.java: -------------------------------------------------------------------------------- 1 | package za.co.riggaroo.retrofittestexample.interceptor; 2 | 3 | import android.util.Log; 4 | 5 | import com.squareup.okhttp.Interceptor; 6 | import com.squareup.okhttp.Request; 7 | import com.squareup.okhttp.Response; 8 | 9 | import java.io.IOException; 10 | 11 | 12 | /** 13 | * @author rebeccafranks 14 | * @since 15/10/23. 15 | */ 16 | public class LoggingInterceptor implements Interceptor { 17 | @Override 18 | public Response intercept(Interceptor.Chain chain) throws IOException { 19 | Request request = chain.request(); 20 | 21 | long t1 = System.nanoTime(); 22 | Log.d("Retrofit",String.format("Sending request %s on %s%n%s", 23 | request.url(), chain.connection(), request.headers())); 24 | 25 | Response response = chain.proceed(request); 26 | 27 | long t2 = System.nanoTime(); 28 | Log.d("Retrofit", String.format("Received response for %s in %.1fms%n%s", 29 | response.request().url(), (t2 - t1) / 1e6d, response.headers())); 30 | 31 | return response; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /RetrofitTestExample/app/src/main/java/za/co/riggaroo/retrofittestexample/pojo/Contents.java: -------------------------------------------------------------------------------- 1 | package za.co.riggaroo.retrofittestexample.pojo; 2 | 3 | /** 4 | * @author rebeccafranks 5 | * @since 15/10/23. 6 | */ 7 | import java.util.ArrayList; 8 | import java.util.HashMap; 9 | import java.util.List; 10 | import java.util.Map; 11 | import com.fasterxml.jackson.annotation.JsonAnyGetter; 12 | import com.fasterxml.jackson.annotation.JsonAnySetter; 13 | import com.fasterxml.jackson.annotation.JsonIgnore; 14 | import com.fasterxml.jackson.annotation.JsonInclude; 15 | import com.fasterxml.jackson.annotation.JsonProperty; 16 | import com.fasterxml.jackson.annotation.JsonPropertyOrder; 17 | 18 | @JsonInclude(JsonInclude.Include.NON_NULL) 19 | @JsonPropertyOrder({ 20 | "quotes" 21 | }) 22 | public class Contents { 23 | 24 | @JsonProperty("quotes") 25 | private List quotes = new ArrayList<>(); 26 | @JsonIgnore 27 | private Map additionalProperties = new HashMap<>(); 28 | 29 | /** 30 | * 31 | * @return 32 | * The quotes 33 | */ 34 | @JsonProperty("quotes") 35 | public List getQuotes() { 36 | return quotes; 37 | } 38 | 39 | /** 40 | * 41 | * @param quotes 42 | * The quotes 43 | */ 44 | @JsonProperty("quotes") 45 | public void setQuotes(List quotes) { 46 | this.quotes = quotes; 47 | } 48 | 49 | @JsonAnyGetter 50 | public Map getAdditionalProperties() { 51 | return this.additionalProperties; 52 | } 53 | 54 | @JsonAnySetter 55 | public void setAdditionalProperty(String name, Object value) { 56 | this.additionalProperties.put(name, value); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /RetrofitTestExample/app/src/main/java/za/co/riggaroo/retrofittestexample/pojo/Error.java: -------------------------------------------------------------------------------- 1 | package za.co.riggaroo.retrofittestexample.pojo; 2 | 3 | import com.fasterxml.jackson.annotation.JsonAnyGetter; 4 | import com.fasterxml.jackson.annotation.JsonAnySetter; 5 | import com.fasterxml.jackson.annotation.JsonIgnore; 6 | import com.fasterxml.jackson.annotation.JsonInclude; 7 | import com.fasterxml.jackson.annotation.JsonProperty; 8 | import com.fasterxml.jackson.annotation.JsonPropertyOrder; 9 | 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | /** 14 | * @author rebeccafranks 15 | * @since 15/10/23. 16 | */ 17 | @JsonInclude(JsonInclude.Include.NON_NULL) 18 | @JsonPropertyOrder({ 19 | "code", 20 | "message" 21 | }) 22 | public class Error { 23 | 24 | @JsonProperty("code") 25 | private Integer code; 26 | @JsonProperty("message") 27 | private String message; 28 | @JsonIgnore 29 | private Map additionalProperties = new HashMap(); 30 | 31 | /** 32 | * 33 | * @return 34 | * The code 35 | */ 36 | @JsonProperty("code") 37 | public Integer getCode() { 38 | return code; 39 | } 40 | 41 | /** 42 | * 43 | * @param code 44 | * The code 45 | */ 46 | @JsonProperty("code") 47 | public void setCode(Integer code) { 48 | this.code = code; 49 | } 50 | 51 | /** 52 | * 53 | * @return 54 | * The message 55 | */ 56 | @JsonProperty("message") 57 | public String getMessage() { 58 | return message; 59 | } 60 | 61 | /** 62 | * 63 | * @param message 64 | * The message 65 | */ 66 | @JsonProperty("message") 67 | public void setMessage(String message) { 68 | this.message = message; 69 | } 70 | 71 | @JsonAnyGetter 72 | public Map getAdditionalProperties() { 73 | return this.additionalProperties; 74 | } 75 | 76 | @JsonAnySetter 77 | public void setAdditionalProperty(String name, Object value) { 78 | this.additionalProperties.put(name, value); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /RetrofitTestExample/app/src/main/java/za/co/riggaroo/retrofittestexample/pojo/Quote.java: -------------------------------------------------------------------------------- 1 | package za.co.riggaroo.retrofittestexample.pojo; 2 | 3 | /** 4 | * @author rebeccafranks 5 | * @since 15/10/23. 6 | */ 7 | import java.util.ArrayList; 8 | import java.util.HashMap; 9 | import java.util.List; 10 | import java.util.Map; 11 | import com.fasterxml.jackson.annotation.JsonAnyGetter; 12 | import com.fasterxml.jackson.annotation.JsonAnySetter; 13 | import com.fasterxml.jackson.annotation.JsonIgnore; 14 | import com.fasterxml.jackson.annotation.JsonInclude; 15 | import com.fasterxml.jackson.annotation.JsonProperty; 16 | import com.fasterxml.jackson.annotation.JsonPropertyOrder; 17 | 18 | @JsonInclude(JsonInclude.Include.NON_NULL) 19 | @JsonPropertyOrder({ 20 | "quote", 21 | "length", 22 | "author", 23 | "tags", 24 | "category", 25 | "id" 26 | }) 27 | public class Quote { 28 | 29 | @JsonProperty("quote") 30 | private String quote; 31 | @JsonProperty("length") 32 | private String length; 33 | @JsonProperty("author") 34 | private String author; 35 | @JsonProperty("tags") 36 | private List tags = new ArrayList<>(); 37 | @JsonProperty("category") 38 | private String category; 39 | @JsonProperty("id") 40 | private String id; 41 | @JsonIgnore 42 | private Map additionalProperties = new HashMap<>(); 43 | 44 | /** 45 | * 46 | * @return 47 | * The quote 48 | */ 49 | @JsonProperty("quote") 50 | public String getQuote() { 51 | return quote; 52 | } 53 | 54 | /** 55 | * 56 | * @param quote 57 | * The quote 58 | */ 59 | @JsonProperty("quote") 60 | public void setQuote(String quote) { 61 | this.quote = quote; 62 | } 63 | 64 | /** 65 | * 66 | * @return 67 | * The length 68 | */ 69 | @JsonProperty("length") 70 | public String getLength() { 71 | return length; 72 | } 73 | 74 | /** 75 | * 76 | * @param length 77 | * The length 78 | */ 79 | @JsonProperty("length") 80 | public void setLength(String length) { 81 | this.length = length; 82 | } 83 | 84 | /** 85 | * 86 | * @return 87 | * The author 88 | */ 89 | @JsonProperty("author") 90 | public String getAuthor() { 91 | return author; 92 | } 93 | 94 | /** 95 | * 96 | * @param author 97 | * The author 98 | */ 99 | @JsonProperty("author") 100 | public void setAuthor(String author) { 101 | this.author = author; 102 | } 103 | 104 | /** 105 | * 106 | * @return 107 | * The tags 108 | */ 109 | @JsonProperty("tags") 110 | public List getTags() { 111 | return tags; 112 | } 113 | 114 | /** 115 | * 116 | * @param tags 117 | * The tags 118 | */ 119 | @JsonProperty("tags") 120 | public void setTags(List tags) { 121 | this.tags = tags; 122 | } 123 | 124 | /** 125 | * 126 | * @return 127 | * The category 128 | */ 129 | @JsonProperty("category") 130 | public String getCategory() { 131 | return category; 132 | } 133 | 134 | /** 135 | * 136 | * @param category 137 | * The category 138 | */ 139 | @JsonProperty("category") 140 | public void setCategory(String category) { 141 | this.category = category; 142 | } 143 | 144 | /** 145 | * 146 | * @return 147 | * The id 148 | */ 149 | @JsonProperty("id") 150 | public String getId() { 151 | return id; 152 | } 153 | 154 | /** 155 | * 156 | * @param id 157 | * The id 158 | */ 159 | @JsonProperty("id") 160 | public void setId(String id) { 161 | this.id = id; 162 | } 163 | 164 | @JsonAnyGetter 165 | public Map getAdditionalProperties() { 166 | return this.additionalProperties; 167 | } 168 | 169 | @JsonAnySetter 170 | public void setAdditionalProperty(String name, Object value) { 171 | this.additionalProperties.put(name, value); 172 | } 173 | 174 | } 175 | -------------------------------------------------------------------------------- /RetrofitTestExample/app/src/main/java/za/co/riggaroo/retrofittestexample/pojo/QuoteOfTheDayErrorResponse.java: -------------------------------------------------------------------------------- 1 | package za.co.riggaroo.retrofittestexample.pojo; 2 | 3 | /** 4 | * @author rebeccafranks 5 | * @since 15/10/23. 6 | */ 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | import com.fasterxml.jackson.annotation.JsonAnyGetter; 10 | import com.fasterxml.jackson.annotation.JsonAnySetter; 11 | import com.fasterxml.jackson.annotation.JsonIgnore; 12 | import com.fasterxml.jackson.annotation.JsonInclude; 13 | import com.fasterxml.jackson.annotation.JsonProperty; 14 | import com.fasterxml.jackson.annotation.JsonPropertyOrder; 15 | 16 | @JsonInclude(JsonInclude.Include.NON_NULL) 17 | @JsonPropertyOrder({ 18 | "error" 19 | }) 20 | public class QuoteOfTheDayErrorResponse { 21 | 22 | @JsonProperty("error") 23 | private Error error; 24 | @JsonIgnore 25 | private Map additionalProperties = new HashMap<>(); 26 | 27 | /** 28 | * 29 | * @return 30 | * The error 31 | */ 32 | @JsonProperty("error") 33 | public Error getError() { 34 | return error; 35 | } 36 | 37 | /** 38 | * 39 | * @param error 40 | * The error 41 | */ 42 | @JsonProperty("error") 43 | public void setError(Error error) { 44 | this.error = error; 45 | } 46 | 47 | @JsonAnyGetter 48 | public Map getAdditionalProperties() { 49 | return this.additionalProperties; 50 | } 51 | 52 | @JsonAnySetter 53 | public void setAdditionalProperty(String name, Object value) { 54 | this.additionalProperties.put(name, value); 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /RetrofitTestExample/app/src/main/java/za/co/riggaroo/retrofittestexample/pojo/QuoteOfTheDayResponse.java: -------------------------------------------------------------------------------- 1 | package za.co.riggaroo.retrofittestexample.pojo; 2 | 3 | /** 4 | * @author rebeccafranks 5 | * @since 15/10/23. 6 | */ 7 | 8 | 9 | import java.util.HashMap; 10 | import java.util.Map; 11 | 12 | import com.fasterxml.jackson.annotation.JsonAnyGetter; 13 | import com.fasterxml.jackson.annotation.JsonAnySetter; 14 | import com.fasterxml.jackson.annotation.JsonIgnore; 15 | import com.fasterxml.jackson.annotation.JsonInclude; 16 | import com.fasterxml.jackson.annotation.JsonProperty; 17 | import com.fasterxml.jackson.annotation.JsonPropertyOrder; 18 | 19 | @JsonInclude(JsonInclude.Include.NON_NULL) 20 | @JsonPropertyOrder({ 21 | "success", 22 | "contents" 23 | }) 24 | public class QuoteOfTheDayResponse { 25 | 26 | @JsonProperty("success") 27 | private Success success; 28 | @JsonProperty("contents") 29 | private Contents contents; 30 | @JsonIgnore 31 | private Map additionalProperties = new HashMap<>(); 32 | 33 | /** 34 | * @return The success 35 | */ 36 | @JsonProperty("success") 37 | public Success getSuccess() { 38 | return success; 39 | } 40 | 41 | /** 42 | * @param success The success 43 | */ 44 | @JsonProperty("success") 45 | public void setSuccess(Success success) { 46 | this.success = success; 47 | } 48 | 49 | /** 50 | * @return The contents 51 | */ 52 | @JsonProperty("contents") 53 | public Contents getContents() { 54 | return contents; 55 | } 56 | 57 | /** 58 | * @param contents The contents 59 | */ 60 | @JsonProperty("contents") 61 | public void setContents(Contents contents) { 62 | this.contents = contents; 63 | } 64 | 65 | @JsonAnyGetter 66 | public Map getAdditionalProperties() { 67 | return this.additionalProperties; 68 | } 69 | 70 | @JsonAnySetter 71 | public void setAdditionalProperty(String name, Object value) { 72 | this.additionalProperties.put(name, value); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /RetrofitTestExample/app/src/main/java/za/co/riggaroo/retrofittestexample/pojo/Success.java: -------------------------------------------------------------------------------- 1 | package za.co.riggaroo.retrofittestexample.pojo; 2 | 3 | /** 4 | * @author rebeccafranks 5 | * @since 15/10/23. 6 | */ 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | import com.fasterxml.jackson.annotation.JsonAnyGetter; 10 | import com.fasterxml.jackson.annotation.JsonAnySetter; 11 | import com.fasterxml.jackson.annotation.JsonIgnore; 12 | import com.fasterxml.jackson.annotation.JsonInclude; 13 | import com.fasterxml.jackson.annotation.JsonProperty; 14 | import com.fasterxml.jackson.annotation.JsonPropertyOrder; 15 | 16 | @JsonInclude(JsonInclude.Include.NON_NULL) 17 | @JsonPropertyOrder({ 18 | "total" 19 | }) 20 | public class Success { 21 | 22 | @JsonProperty("total") 23 | private Integer total; 24 | @JsonIgnore 25 | private Map additionalProperties = new HashMap<>(); 26 | 27 | /** 28 | * 29 | * @return 30 | * The total 31 | */ 32 | @JsonProperty("total") 33 | public Integer getTotal() { 34 | return total; 35 | } 36 | 37 | /** 38 | * 39 | * @param total 40 | * The total 41 | */ 42 | @JsonProperty("total") 43 | public void setTotal(Integer total) { 44 | this.total = total; 45 | } 46 | 47 | @JsonAnyGetter 48 | public Map getAdditionalProperties() { 49 | return this.additionalProperties; 50 | } 51 | 52 | @JsonAnySetter 53 | public void setAdditionalProperty(String name, Object value) { 54 | this.additionalProperties.put(name, value); 55 | } 56 | 57 | } 58 | 59 | -------------------------------------------------------------------------------- /RetrofitTestExample/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 17 | 18 |