Model
后端返回的结果都比较统一,一般包含 code
,msg
, data
,创建的 model
使用泛型。
public class Result<T> {
private int code;
private String msg;
private T data;
// getter & setter
}
subModel
public class SubModel {
private long state;
private long remain;
private long total;
// getter & setter
}
Retrofit 网络库
官方网站:https://square.github.io/retrofit/
配置 app 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")
}
Server
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();
}
Injection 注入
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);
}
}
Unit Test 单元测试
async 异步测试
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:
java.lang.RuntimeException: Method d in android.util.Log not mocked. See http://g.co/androidstudio/not-mocked for details.
在 build.gradle
下面 android 项目下添加:
android {
...
testOptions {
unitTests.returnDefaultValues = true
}
}
添加测试用例
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);
}
}
网友评论