本文適合這幾類同學(xué)閱讀:熟悉使用Junit4、okhttp與retrofit的,閑著無聊的。
??Android中有關(guān)網(wǎng)絡(luò)的開發(fā)通常伴隨著整個(gè)應(yīng)用的開發(fā)過程,而在這個(gè)過程中,大多數(shù)都是采用的手動(dòng)測(cè)試,即運(yùn)行在真機(jī)或模擬器中進(jìn)行真實(shí)的網(wǎng)絡(luò)連接測(cè)試,這樣做難免會(huì)浪費(fèi)一些時(shí)間。但若應(yīng)用中使用的是okhttp,則有一個(gè)非常方便省時(shí)的辦法,即使用MockWebServer進(jìn)行單元測(cè)試。
??本文將使用MockWebServer并結(jié)合retrofit,介紹Android中網(wǎng)絡(luò)部分的單元測(cè)試。
一.準(zhǔn)備
在此,默認(rèn)已在工程中使用了okhttp與retrofit,接下來,在Module的build.gradle中引入MockWebServer:
dependencies {
testCompile 'com.squareup.okhttp3:mockwebserver:3.8.1' //本文編寫時(shí)的最新版本
}
二.開始測(cè)試
1.新建測(cè)試文件WebTest.java:
@RunWith(JUnit4.class)
public class WebTest {
}
2.聲明并實(shí)例化MockWebServer:
@RunWith(JUnit4.class)
public class WebTest {
@Rule
public final MockWebServer mockWebServer = new MockWebServer();
}
若不使用@Rule標(biāo)記MockWebServer,則需在@Before與@After中分別調(diào)用其start()與shutdown()方法。
3.聲明retrofit的service,此處分別測(cè)試MockWebServer的兩種請(qǐng)求響應(yīng)策略:隊(duì)列與轉(zhuǎn)發(fā)器
private interface Service {
@FormUrlEncoded
@POST("modify")
Call<Person> modifyPerson(@Field("name") String name);
@GET("person/{id}")
Call<Person> fetchPersonById(@Path("id") int id);
}
其中的實(shí)體類將在文末給出,實(shí)際開發(fā)中可使用真實(shí)地址,此處僅為假設(shè)。
4.實(shí)例化Service:
@Before
public void setup() {
service = new Retrofit.Builder()
.baseUrl(mockWebServer.url("/")) //實(shí)際項(xiàng)目中可使用真實(shí)url
.addConverterFactory(FastJsonConverterFactory.create())
.build()
.create(Service.class);
}
此處使用fastjson解析返回的json數(shù)據(jù),其中若要使用FastJsonConverterFactory請(qǐng)?zhí)砑尤缦乱蕾嚕?br>
在根build.gradle中添加:
allprojects {
repositories {
maven { url "https://jitpack.io" }
}
}
在module的build.gradle中添加:
dependencies {
compile 'com.github.ZYRzyr:FastJsonConverter:v1.3-beta'
}
5.隊(duì)列響應(yīng)
調(diào)用MockWebServer的enqueue(MockResponse response)方法即可模擬一次請(qǐng)求響應(yīng):
@Test
public void testPOST() throws Exception {
//模擬服務(wù)器的response
mockWebServer.enqueue(new MockResponse().setBody("{\"name\": \"Tom\",\"age\": 100}"));
Call<Person> call = service.modifyPerson("Tom");
Person person = call.execute().body();
assertNotNull(person);
assertEquals("Tom", person.getName());
assertEquals(100, person.getAge());
assertEquals("POST", mockWebServer.takeRequest().getMethod());
}
6.轉(zhuǎn)發(fā)器響應(yīng)
需要手動(dòng)編寫Dispatcher并設(shè)置給MockWebServer:
@Test
public void testGET_WithParam() throws Exception {
mockWebServer.setDispatcher(dispatcher); //dispatcher見下文
Call<Person> call = service.fetchPersonById(5);
Person person = call.execute().body();
assertNotNull(person);
assertEquals("A", person.getName());
assertEquals(11, person.getAge());
assertEquals("GET", mockWebServer.takeRequest().getMethod());
}
dispatcher:
//dispatcher即為上文中的 mockWebServer.setDispatcher(dispatcher);
private final Dispatcher dispatcher = new Dispatcher() {
@Override
public MockResponse dispatch(RecordedRequest request) throws InterruptedException {
switch (request.getPath()) {
case "/person/5": //5即為GET請(qǐng)求fetchPersonById(@Path("id") int id)中的請(qǐng)求參數(shù)
return new MockResponse().setResponseCode(200).setBody("{\"name\": \"A\",\"age\": 11}");
default:
return new MockResponse().setResponseCode(404);
}
}
};
上文中的實(shí)體類Person.java:
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
...省略getter、setter方法
}
最后
使用了MockWebServer進(jìn)行API測(cè)試,直接省了很多編譯、運(yùn)行的時(shí)間,心情都要好了很多。若想了解更多的關(guān)于MockWebServer本身的東西,可以直接去它老巢查看。
原文作者/ZYRzyr
原文鏈接:http://www.itdecent.cn/p/e906f7ee2a04
請(qǐng)進(jìn)入這里獲取授權(quán):https://101709080007647.bqy.mobi