android 单元测试

单元测试的重要的和必要性这里不在强调,本文介绍几个常用的单元测试的框架

JUnit4

JUnit4是一个java的单元测试框架,多数Java的开发环境都已经集成了JUnit作为单元测试的工具,android studio默认继承了JUNit4

testImplementation 'junit:junit:4.12'

JUnit4主要是通过注解的方式来识别测试方法,下面介绍几个常用的方法以及它的作用:
* @BeforeClass 在执行所有测试方法之前执行,只执行一次,对应方法必须是静态方法
* @Before 在任意使用@Test注解标注方法执行之前执行
* @Test 测试方法
* @After 在任意使用@Test注解标注方法执行之后执行
* @AfterClass 在执行所有测试方法之后执行,只执行一次,对应方法必须是静态方法

了解完以上的信息还没有完结,单元测试还有很重要的一点验证结果,一般是通过一些assert方法来完成的,JUnit为我们提供的assert方法,多数都在Assert这个类里面

  • Assert.assertEquals 验证执行结果与期盼结果比较,这个方法的参数有很多种,根据需要使用
  • Assert.assertFalse 验证参数为false
  • Assert.assertNotNull 验证参数不为空
  • Assert.assertNotSame 参数中的两个对象不是同一个对象
  • Assert.assertNull 验证参数为空
  • Assert.assertSame 参数中的两个对象是同一个对象
  • Assert.assertThat 实际情况满足匹配器给出的条件
  • Assert.assertTrue 验证参数为true

由于很多地方用到了Assert.assertThat方法,下面列一下啊Matcher常用的方法

  • Matcher.allOf
  • Matcher.anyOf
  • Matcher.both
  • Matcher.containsString
  • Matcher.describedAs
  • Matcher.either
  • Matcher.endsWith
  • Matcher.equalTo
  • Matcher.instanceOf
  • Matcher.is
  • Matcher.hasItem

JUnit单元测试时是不能使用Android相关的类的,下面就来认识一下Robolectric框架

Robolectric

Robolectric框架是针对android的测试框架,使用Robolectric框架进行单元测试不用依赖真机或者模拟器,Robolectric支持单元测试范围从Activity的跳转、Activity展示View(包括菜单)和Fragment到View的点击触摸以及事件响应,同时Robolectric也能测试Toast和Dialog。对于需要网络请求数据的测试,Robolectric可以模拟网络请求的response。对于一些Robolectric不能测试的对象,比如ConcurrentTask,可以通过自定义Shadow的方式现实测试。下面将着重介绍Robolectric的常见用法。

引入

testCompile "org.robolectric:robolectric:3.6.1"

官方给出的demo

@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class)
public class MyActivityTest {

  @Test
  public void clickingButton_shouldChangeResultsViewText() throws Exception {
    Activity activity = Robolectric.setupActivity(MyActivity.class);

    Button button = (Button) activity.findViewById(R.id.press_me_button);
    TextView results = (TextView) activity.findViewById(R.id.results_text_view);

    button.performClick();
    assertThat(results.getText().toString(), equalTo("Testing Android Rocks!"));
  }
}

@RunWith(RobolectricGradleTestRunner.class)表示用Robolectric的TestRunner来跑这些test,通过gradle CLI或者Android studio运行为单元测试定制的测试运行程序,有一条件必须配置@Config

@RunWith(RobolectricTestRunner.class)提供Android运行时的模拟环境

Robolectric框架通过shadow类替换对应的真实方法,最终实现测试脱离底层实现,感兴趣的话,可以自行了解

Mock

对于一些依赖关系复杂的测试对象,可以采用Mock框架解除依赖,常用的有Mockito,mock创建一个类的虚假的对象,用于解耦真实对象所需要的依赖,Mock得到的对象仅仅是具备测试对象的类型,并不是真实的对象,也就是并没有执行过真实对象的逻辑。

引入

repositories { jcenter() }
dependencies { testCompile "org.mockito:mockito-core:2.+" }

Mock的方法使用

// mock creation
List mockedList = mock(List.class);

// using mock object - it does not throw any "unexpected interaction" exception
mockedList.add("one");
mockedList.clear();

// selective, explicit, highly readable verification
verify(mockedList).add("one");
verify(mockedList).clear();

直接通过mock方法创建虚拟对象,也可以使用注解的方式 @Mock 来创建,通过 verify 方法来检查相应方法是否调用

stub形式的使用

// you can mock concrete classes, not only interfaces
LinkedList mockedList = mock(LinkedList.class);

// stubbing appears before the actual execution
when(mockedList.get(0)).thenReturn("first");

// the following prints "first"
System.out.println(mockedList.get(0));

// the following prints "null" because get(999) was not stubbed
System.out.println(mockedList.get(999));

指定关键字 when 返回一个 OngoingStubbing 接口,通过其提供的 thenReturn,thenThrow,thenCallRealMethod 及自定义 thenAnswer 来返回相应的结果

Mock中几个主要的方法

  • mock()/@Mock: 创建一个Mock虚拟对象
  • spy()/@Spy: 部分mock,真正的方法会被调用,但是仍然需要验证
  • verify(): 检测方法是否被调用

通过 times,never,atLeastOnce,atLeast,atMost 这些方法,我们可以对一个方法的调用次数做判断

verify(mockedList, atLeastOnce()).add("three times")

通过doThrow为一个方法的调用添加异常,验证代码对异常的处理

doThrow(new RuntimeException()).when(mockedList).clear();

通过Mockito的inOrder方法验证调用顺序

更多使用方法请参考mock官网

注:final类型、private类型以及静态类型的方法不能mock

总结

JUnit框架主要是用来测试java类的,既能做单元测试也能做集成测试,如果想要调用android的方法需要用到Robolectric框架,这两个框架可以做的事情很多,几乎能满足你所有的需求,但是有的时候测试需要用到虚拟对象,就需要用到Mock框架了。

希望这篇文章,对初次接触单元测试的你有所帮助

参考文献:
* https://github.com/junit-team/junit4
* https://github.com/robolectric/robolectric
* https://tech.meituan.com/Android_unit_test.html
* http://site.mockito.org/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值