後端返回的結果都比較統一,通常包含 code
,msg
, data
,建立的 model
使用泛型。java
public class Result<T> {
private int code;
private String msg;
private T data;
// getter & setter
}
複製代碼
public class SubModel {
private long state;
private long remain;
private long total;
// getter & setter
}
複製代碼
官方網站:square.github.io/retrofit/android
build.gradle
dependencies {
...
implementation 'com.squareup.retrofit2:retrofit:2.6.0'
implementation 'com.squareup.retrofit2:converter-gson:2.6.0'
implementation("com.squareup.okhttp3:logging-interceptor:3.14.2")
}
複製代碼
public interface Service {
@FormUrlEncoded
@POST("ctrl")
Call<Result> sendCmd(@Field("cmd") String cmd, @Field("arg") String arg);
@POST("config")
Call<Result<Config>> fetchConfig();
@POST("state")
Call<Result<State>> fetchState();
@POST("tfcard")
Call<Result<TFCard>> fetchTFCard();
}
複製代碼
public class Injection {
// 建立 SingleObject 的一個對象
private static Injection instance = new Injection();
// 讓構造函數爲 private,這樣該類就不會被實例化
private Injection(){}
// 獲取惟一可用的對象
public static Injection getInstance(){
return instance;
}
private Retrofit provideRetrofit() {
final String BASE_URL = "http://127.0.0.1:5000/api/";
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(provideOkHttpClient())
.build();
return retrofit;
}
private OkHttpClient provideOkHttpClient() {
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(provideLoggingInterceptor());
return httpClient.build();
}
private HttpLoggingInterceptor provideLoggingInterceptor() {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
if (BuildConfig.DEBUG) {
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
} else {
logging.setLevel(HttpLoggingInterceptor.Level.NONE);
}
return logging;
}
public Service provideService() {
return provideRetrofit().create(Service.class);
}
}
複製代碼
public void testSomething() {
final CountDownLatch signal = new CountDownLatch(1);
Service.doSomething(new Callback() {
@Override
public void onResponse() {
// test response data
// assertEquals(..
// assertTrue(..
// etc
signal.countDown(); // notify the count down latch
}
});
signal.await(); // wait for callback
}
複製代碼
java.lang.RuntimeException: Method d in android.util.Log not mocked. See http://g.co/androidstudio/not-mocked for details.
複製代碼
在 build.gradle
下面 android 項目下添加:git
android {
...
testOptions {
unitTests.returnDefaultValues = true
}
}
複製代碼
添加測試用例github
public class InjectionTest {
@Test
public void provideRecoderServiceTFCard() throws Throwable {
final CountDownLatch signal = new CountDownLatch(1);
Call<Result<TFCard>> call = Injection.getInstance().provideRecoderService().fetchTFCard();
call.enqueue(new Callback<Result<TFCard>>() {
@Override
public void onResponse(Call<Result<TFCard>> call, Response<Result<TFCard>> response) {
Result result = response.body();
TFCard tfCard = (TFCard) result.getData();
LogUtils.d("tfCard", tfCard.toString());
signal.countDown();
}
@Override
public void onFailure(Call<Result<TFCard>> call, Throwable t) {
LogUtils.d("InjectionTest", t.getMessage());
signal.countDown();
}
});
signal.await(3, TimeUnit.SECONDS);
}
}
複製代碼