Android测试:Mockito and Robolectric

原文地址:

http://alexzh.com/tutorials/android-testing-mockito-robolectric/

译文

这是Android测试项目系列文章的第二篇。你可以在这里(http://alexzh.com/tutorials/android-testing-unit-testing/)读到第一篇关于“单元测试”的文章。所有的源代码都托管到Github。Github上面的项目有不同的分支:

app的基本版本:

https://github.com/AlexZhukovich/SimpleCoffeeOrderTestProject/tree/1_simple_coffee_order

有单元测试的基本版本app:

https://github.com/AlexZhukovich/SimpleCoffeeOrderTestProject/tree/2_unit_tests

基本版本 + payment activity:

https://github.com/AlexZhukovich/SimpleCoffeeOrderTestProject/tree/3_simple_coffee_order_paymentActivity

mockito and robolectric tests:

https://github.com/AlexZhukovich/SimpleCoffeeOrderTestProject/tree/4_mockito_and_robolectric_tests

unit testing的局限性

Unit test测试的类必须是独立性的。虽然我们常常可以达到测试的目的,但是Java类往往需要依赖其他很多类。为解决这个问题,我们需要多次测试。

不同的对象(test中的各种对象)

dummy object(虚拟对象)被传来传去但是从未被使用过,意思是他的方法从来没有被使用过,对象就像参数一样被传递。

fake object具有工作实现,但是通常被简化。

stub class是类或接口的部分实现,目的是用于测试。

mock object是为方法调用定义的类或接口的虚拟实现。

生成Mock Object对象

你可以手动创建一个mock对象或使用Mock框架来模拟这个类,其实一个mock对象的就是一个数据的提供者。应用在生产中使用真实的数据库,但是在测试中使用mock对象来模拟数据库以确保测试条件总是相同的。

Mocking框架

Mock框架要求创建mock对象尽可能的简单。比较常用的框架有:

EasyMock:http://easymock.org/,

Mockito:http://mockito.org/.

Mockito的简单介绍

Mockito(http://mockito.org/)是目前比较常用mock框架,它可以与JUnit一起使用。Mockito(http://mockito.org/)允许你自己创建并配置mock对象。

项目中添加Mockito依赖

如果你使用的是gradle系统构建的,在你的“build.gradle”文件中添加下面的依赖:

1. 使用Mockit API

(1)创建并配置mock对象

Mockito允许使用static mock()方法来创建mock对象;

or

执行when(...).thenReturn(...)方法需要建立明确的传入特定条件并返回本次测试的值。你也可以使用像anyInt(),anyFloat(),anyList()等这样的方法明确输入值的类型并返回却确定的值;

doReturn(…).when(…).methodCall方法工作原理类似,但在void方法(无参数返回的方法)中比较常用。

doThrow主体也可用于无参返回的方法void,可以捕获方法中的异常。

(2)确保调用mock对象

你也可以使用verify()方法去保证该方法一定被调用

(3)限制

Final classes(final 类)

Anonymous classes (匿名类)

Primitive types (基本类型)

下面是Android Test的一些限制

如果我们运行这个测试,你会发现如下的错误提示信息。

仍然有很多基本的类的方法不能被模拟,但是可以使用Robolectric来代替。

2. Robolectric

在Android中进行单元测试一直比较困难,但是使用Rebolectric相对来说比较容易。

这个库还允许你通过删除抛出RuntimeExceptions的 stubs 来模拟 Android SDK的API。

Robolectric是一个运行在JVM上面的单元测试的三方库。同时该库也允许进行测试驱动开发(TDD)。

Robolectric通过所谓的shadow对象替换了所有的Android类。

如果一个方法是由Robolectric实现的,它会将这些方法调用转发给shadow对象,该对象的行为类似于Android SDK的对象。如果shadow对象未实现某个方法,则只返回默认值,如 null 或 0;

接下来看看一下如果在Android项目中如何配置Robolectric,以下是最简单的在build.gradle配置方法。

如果你想使用 Shadow对象,需要在项目中添加Maven依赖

接着,就可以使用Robolectric来创建 Android test。在同名tests包下,你可以创建一个新类(android test包是用来放instrumental test代码,而test包是用来放local JVM 测试代码)。接着也通过注解的方式为该类创建一个Runner和config,来使test可执行。

我们同时也需要为应用添加一些改动。首先,我想要增加一个付款页面,为此需要增加布局文件、activity文件、修改AndroidManifest文件配置:

activity_payment.xml布局:

PaymentActivity.java

最后在AndroidManifest.xml文件注册activity.

如果我们要在MainActivity中的 “Pay“ 按钮添加并绑定点击事件来执行下一步的操作。我使用下面这行代码来打开一个新的activity。

第一个Robolectric测试:我们可以检测MainActivity是否存在。在这个例子中,我们需要创建一个MainActivity类来检测。接下来就需要对比这个对象是否为null。

接下来需要测试验证的就是价格标签,这个应用中有2个标签用来显示价格。

下一个例子验证咖啡数量选择器(加号按钮,数量标签,减号按钮 三个功能)。

下一个测试例子验证 增加按钮和减少按钮如何工作。

下一个测试例子验证支付按钮是否存在。

下一个测试例子验证Intent启动PaymentActivity是否正确。

最后一个例子测试 点击 “pay”按钮后 MainActivity是否能打开 PaymentActivity。

在下面的类中你可以找到全部的源码。

然而,上面这个源码写得并不是那么好,接下来我将修改一下这段代码。在之前的例子中,几乎所有的方法都有activity的创建和初始化的代码。但是一些View的初始化,如TextViewButtons,这些部分的代码都可以放在有@Before注解的方法中。因为@Before注解的方法是在每个测试之前执行的。下面MainActivityTest代码片段做了一些修改:

在写接下来的测试之前,我们需要了解一些创建activity有很多种方法。最简单的方法你可以使用setupActivity(Class activityClass)方法床架activity,但是如果你想使用Intent传递更多的数据,这就不能满足我们的需求。但是还可以使用另一种方法,buildActivity(Class activityClass),以及一些链式操作,如:withIntent(SOME_INTENT),create(),start(),resume(),visible(), andget()。当然,你可以在这个链式操作中,任意改变或者增加一些方法。同时setupActivity方法也可以触发一系列的动作:create(),start(),postCreate(null),resume(),visible(), andget().

我们可以开始为PaymentActivity写测试。

我们已经完成了这个App的所有测试。现在我们可以调试所有的测试,此时你可以看到所有的测试是否正确运行。

源码托管在Github(https://github.com/AlexZhukovich/SimpleCoffeeOrderTestProject),可在不同分支查看。

资源:

Mockito:http://site.mockito.org/

Robolectric:http://robolectric.org/

Unit testing with Mockito:

http://www.vogella.com/tutorials/Mockito/article.html

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180924G17K6Q00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券