Android 单元测试之Roboletric RxJava、Retrofit、访问真实网络、虚拟服务器

原创 2016年08月29日 08:57:49

Android 单元测试之Roboletric RxJava、Retrofit、访问真实网络、虚拟服务器

Android 单元测试之JUnit和Mockito
Android 单元测试之Roboletric 环境配置
Android 单元测试之Roboletric的简单使用
Android 单元测试之Roboletric RxJava、Retrofit、访问真实网络、虚拟服务器
Android 单元测试之Espresso - Google官方UI测试框架

添加依赖

android {
    ...
    configurations.all {
        resolutionStrategy {
            force 'com.android.support:support-annotations:24.1.1'
        }
    }
}

dependencies {
    ...
    testCompile 'junit:junit:4.12'
    testCompile 'org.robolectric:robolectric:3.1.2'
    testCompile 'org.khronos:opengl-api:gl1.1-android-2.1_r1'
    testCompile 'org.hamcrest:hamcrest-all:1.3'
    testCompile 'org.mockito:mockito-all:2.0.2-beta'
    testCompile 'org.robolectric:shadows-httpclient:3.0'
    testCompile 'com.squareup.okhttp3:mockwebserver:3.4.1'
    compile 'org.robolectric:shadows-core-v23:3.1.2'

    compile 'com.android.support:appcompat-v7:24.1.1'
    compile 'io.reactivex:rxjava:1.1.9'
    compile 'io.reactivex:rxandroid:1.2.1'
    compile 'com.android.support:support-annotations:24.1.1'
    compile 'com.squareup.okhttp3:okhttp:3.4.1'  
    compile 'com.squareup.okhttp3:okhttp-urlconnection:3.4.1'
    compile 'com.squareup.retrofit2:retrofit-converters:2.1.0'
    compile 'com.squareup.retrofit2:converter-gson:2.1.0'
    compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
}

RxJava测试

RxJava专门提供了一个TestSubscriber,方便测试

@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 21)
public class MockitoTest {
    @Test
    public void MocksTest() {
        TestSubscriber<Bean> testSubscriber = new TestSubscriber<>();
        getMocks().subscribe(testSubscriber);
        assertThat(testSubscriber.getOnNextEvents().size(), is(3));
    }

    private Observable<Bean> getMocks() {
        return Observable.just(new Bean(), new Bean(), new Bean());
    }
}

虚拟服务器之FakeHttp

@Test
public void reposTest1() throws IOException {

    String mockJsonResult =
            "[{\"id\":19669199,\"name....省略}]";
    FakeHttp.addPendingHttpResponse(200, mockJsonResult);

    HttpGet httpGet = new HttpGet("http://www.baidu.com");
    HttpResponse httpResponse = new DefaultHttpClient().execute(httpGet);
    String result = EntityUtils.toString(httpResponse.getEntity());
    System.out.print(result);
    assertThat(result, is(mockJsonResult));
}

虚拟服务器之MockWebServer

@Test
public void MockServerTest() throws IOException, InterruptedException {
    // 1. 创建服务器
    MockWebServer server = new MockWebServer();

    // 2. 添加预置的响应,响应会按照先进先出的顺序依次返回
    server.enqueue(new MockResponse().setBody("i am ethanco"));
    server.enqueue(new MockResponse().setResponseCode(404).setBody("not found")); //按顺序返回,即如果请求两次,第二次就会返回这个
    server.enqueue(new MockResponse().setResponseCode(503).setBody("hello, world!")); //第三次返回这个

    // 3. 启动服务器
    server.start();

    // 4. 获取请求 url,不能使用普通的 URL,一定要使用 server.url() 返回的 URL,不然没法进入 Mock 服务器
    HttpUrl baseUrl = server.url("/reg1");

    //5.发送请求
    URL url = new URL(baseUrl.url().toString());
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setRequestMethod("GET");
    conn.setConnectTimeout(5000);

    assertEquals(200, conn.getResponseCode());

    InputStream is = conn.getInputStream();
    //把流转化为文本信息  String
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    byte[] buffer = new byte[1024];
    int len = 0;
    while ((len = is.read(buffer)) != -1) {
        bos.write(buffer, 0, len);
    }
    String result = bos.toString();
    bos.close();
    is.close();

    System.out.println(result);

    // server.takeRequest() 是一个阻塞操作,直到接收到请求
    RecordedRequest request1 = server.takeRequest();

    //这里可以查看服务器获取的请求信息,可以查看 http 报文头之类的协议信息
    assertEquals("/reg1", request1.getPath());

    server.shutdown();
}

FakeHttp和MockWebServer都可以模拟服务器进行测试,从而提高开发速度。但推荐使用MockWebServer,因为FakeHttp只支持AndroidHttpClient,而MockWebServer支持所有的网络访问库,包括Retrofit。

通过真实网络访问数据

在此处使用Retrofit

public interface APIService {
    @GET("/users/{user}/repos")
    public Call<List<Repo>> listRepos(@Path("user") String user);

    @GET("/users/{user}/repos")
    public Observable<List<Repo>> listRepos2Observable(@Path("user") String user);
}

访问网络

@Before
public void setUp() {
    apiService = RetrofitFactory.getInstance().createRetrofit("https://api.github.com").create(APIService.class);
}

@Test
public void reposTest2() {
    List<Repo> list = null;
    try {
        list = apiService.listRepos("devinshine").execute().body();
    } catch (IOException e) {
        e.printStackTrace();
    }
    assertThat(list.size(), is(not(0)));
    System.out.print(list.size());
}

@Test
public void reposTestByObservable() {
    int size = apiService.listRepos2Observable("devinshine")
            .flatMap(Observable::from)
            .count()
            .toBlocking()
            .single();
    assertThat(size, is(not(0)));
    System.out.print(size);
}

可能出现的错误

java.lang.AssertionError

解决方法

设置@Config(sdk = 23)  

具体请看 issues

其他

在Android中有assertj-android

是一组面向测试Android AssertJ断言。这个库的扩展于AssertJ,旨在使其更容易测试 Android。

可以用这个代替原生的assert

源码Demo

版权声明:本文为博主原创文章,未经博主允许不得转载。

Android 单元测试之Roboletric 环境配置

Android 单元测试之Roboletric 环境配置 Robolectric由于只在Java虚拟机中运行,速度很快,虽然在API支持上无法和Espresso相比,但速度有很大优势,适合单元测试,尤...
  • EthanCo
  • EthanCo
  • 2016年08月29日 08:54
  • 1405

Android-使用Mockito、Robolectric和RxJava及Retrofit进行单元测试

Android-使用Mockito、Robolectric和RxJava及Retrofit进行单元测试 字数1479 阅读1885 评论6 喜欢22 本文只是对Mockito、Robo...

Android单元测试框架Robolectric3.0介绍(二)

一 闲话单元测试 我们经常讲“前人种树,后人乘凉”,然而在软件开发中,往往呈现出来的却是截然相反的景象,我们在绩效和指标的驱使下,主动或被动的留下来大量坏味道的代码,在短时间内顺利的完成项目,此后却...

BDD, Behavior Driven Development 行为驱动开发 - 敏捷开发第二代浪潮

讲到中国的开发,那是非常独特的,只求达到目的,管它过程是如何的?当然不是说所有中国人的开发都是这样,只是个普遍现象。 我们需要测试么?我们需要代码规范么?如果为了可以节省时间完成目标,还管的了这么多么...
  • aywhen
  • aywhen
  • 2014年03月19日 10:43
  • 1196

京东支付,支付宝网页支付,财付通支付

这些支付均为网页支付,网页支付的工作量均不在手机端,所以遇到这种问题你该庆幸,只需用webview加载一个web端给你的url就好了,支付宝代码如下,其他的和它一模一样,只是url不一样public ...

(MVP+RxJava+Retrofit)解耦+Mockito单元测试 经验分享

photo-1460899960812-f6ee1ecaf117_副本.jpg 前言 首先,对于MVP、RxJava还不了解的同学,请先阅读这几篇文章: Android MVP模式 ...

Android单元测试:使用本地数据测试Retrofit

简述 在日常项目开发中,基本没有什么机会用到Kotlin,几个月前学习的语法,基本上都忘光了,于是自己强迫自己在写Demo中使用Kotlin,同时,在目前开发的项目中开了一个测试分支,用来补全之前没...

Android单元测试:测试RxJava的同步及异步操作

简述在您开发的项目中,您使用了RxJava+Retrofit的网络请求框架,在RxJava强大的操作符下,您理所当然的认为您已经能够游刃有余地处理Android客户端开发中的联网请求需求,比如这样:/...

Rxjava2单元测试的异步和同步转换

自从接触到单元测试后,每次看UT的文章开头就一定会有:单元测试的必要性和好处,这里我就不累述了。 于是我渐渐入坑,加了相关群,虽然学习起来比较吃力,但是渐渐也感觉到了好处 我想,可能是单元测试让我...
  • verymrq
  • verymrq
  • 2017年04月26日 22:04
  • 375
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android 单元测试之Roboletric RxJava、Retrofit、访问真实网络、虚拟服务器
举报原因:
原因补充:

(最多只允许输入30个字)