单元测试
从测试金字塔中我们可以看出,单元测试在整个金子塔中处于基石的地位。一般占有整体测试总量的70%,是测试的重中之重。
#
测试工具名称 | 作用 |
---|---|
Junit | 单元测试框架。 |
Mockito | 模拟依赖的库,主要用于在单元测试中提供模拟依赖。 |
PowerMock | 模拟依赖的库,此库可以模拟 Mockito 无法模拟的一些依赖,如:final、static、private 方法的模拟。 |
#
断言断言是判断程序的执行结果是否符合预期的工具,使用断言是单元测试的基础,要更好的进行单元测试的开发,首先要学会使用断言,为了大家更好的理解单元测试,这里将对Junit
中的断言做一个简要的介绍。
#
Junit 断言assertEquals
/assertNotEquals
验证是否相等,其方法原型如下:
- message:可选消息,提供此参数,将会在发生错误时报告这个消息。
- expected:期望值。
- actual:实际值。
- tolerance:容差,如果比较的是两个浮点数,则表示在这个误差之内会被认为是相等的。
assertNotEquals
与assertEquals
用法相似,语义相反,不再赘述。
assertTrue
/assertFalse
验证是否为真,其方法原型如下:
- message:可选消息,提供此参数,将会在发生错误时报告这个消息。
- condition:待验证的布尔型值。
assertFalse
与assertTrue
用法相似,语义相反,不再赘述。
assertNull
/assertNotNull
验证是否为空(null
),其方法原型如下:
- message:可选消息,提供此参数,将会在发生错误时报告这个消息。
- object:待验证的对象。
assertNotNull
与assertNull
用法相似,语义相反,不再赘述。
assertSame
/assertNotSame
验证对象是否为相同,其方法原型如下:
- message:可选消息,提供此参数,将会在发生错误时报告这个消息。
- expected:期望对象。
- actual:实际对象。
assertNotSame
与assertSame
用法相似,语义相反,不再赘述。
assertArrayEquals
验证数组是否为相等,注意这里比较的是数组中的元素,数组中所有元素相等的情况下,验证通过。其方法原型如下:
- message:可选消息,提供此参数,将会在发生错误时报告这个消息。
- expecteds:期望数组对象。
- actuals:实际数组对象。
fail
执行fail
方法会让验证直接失败。常用于测试异常。
使用场景举例:
以上的代码目标就是测试异常,所以当Password.validate("123")
没有抛出异常时,测试失败,直接调用fail
方法,本次测试失败。
assertThat
查看实际的值是否满足指定验证条件,满足验证条件的情况下,验证通过。
- reason:可选参数,提供此参数,将会在发生错误时报告这个信息。
- actual:实际对象。
- matcher:验证规则。
assertThat
是Junit4
以后加入的断言。这是一个功能十分强大的断言,因为后面的匹配器可以自己扩展,这就为Junit
的断言系统提供了无限的可能。
#
HamcrestHamcrest
是一个断言匹配器的库,使用Hamcrest
可以极大的提高测试断言的可读性。除Java
外,也可以在其他语言中应用 Hamcrest
,如:Python
、Ruby
、Objective-C
、PHP
、Erlang
、Swift
等。
Hamcrest
在与Junit
连用时,可将其视为Junit
中的assertThat
断言的扩展。这个扩展非常强大,可以说是吊打Junit
原生断言的存在。
这里将根据Hamcrest
中API的分类来对其进行一个简要的介绍。
#
核心APIis
is
可以看做是一个语法糖,使用is
匹配器可以使程序更加易懂。当实际值与is
中的条件可以正确匹配时,验证通过。
not
和is
使用方式一样,只是含义相反。当实际值与not
中的条件不匹配时,验证通过。
containsString
当被验证字符串是实际字符串的子串时,验证通过。
startsWith
/endsWith
当实际字符串以被验证字符串开头/结尾时,验证通过。
sameInstance
验证两个对象是否是相同实例。
anyOf
连接两个条件,当其中任意一个条件为真时验证通过,类似OR
的逻辑。
allOf
连接两个条件,当满足其中所有条件为真时验证通过,类似AND
的逻辑。
hasItem
检验集合类中是否存在指定元素,如果存在指定元素,则验证通过。
#
Number 匹配器greaterThan
/lessThan
比较数字大小的断言:
greaterThan
:大于greaterThanOrEqualTo
:大于等于lessThan
:小于lessThanOrEqualTo
:小于等于
closeTo
误差基准与允许范围,使用方式参照示例。
#
Text 匹配器isEmptyString
/isEmptyOrNullString
isEmptyString
:匹配空字符串。isEmptyOrNullString
:匹配空字符串或者null
。
equalToIgnoringCase
/equalToIgnoringWhiteSpace
equalToIgnoringCase
:匹配空字符串相等,忽略大小写。equalToIgnoringWhiteSpace
:匹配空字符串相等,忽略整体左右空格。
stringContainsInOrder
按顺序包含字符串。
#
Collections 匹配器empty
空集合判断。实际集合为空时,验证通过。
hasSize
检查集合元素数量。
#
Bean 匹配器hasProperty
检查Bean对象中是否存在某个属性。
注意,
hasProperty
验证的 Bean 必须是遵循 JavaBean 规范的对象,也就是说,如果上例中的city
类的属性没有getter
与setter
方法,则验证无法通过。
samePropertyValuesAs
检查两个对象中的属性值是否相等,如果相等则验证通过。
#
异步任务在Android开发中不可避免地会涉及到许多的异步任务,异步任务不仅仅在Android开发领域,甚至在整个前端开发领域,都是一个绕不开且无法回避的重要话题。
那么在Android开发的过程中,如何对异步任务做单元测试呢?下面将给出两种基于 Mockito
的解决方案。
Mockito ArgumentCaptor
Mockito
的ArgumentCaptor
对象可以在verify
的时候通过ArgumentCaptor.capture()
方法捕获传入的参数对象,这样我们就可以通过这个方法捕获callback
对象,然后通过手动调用callback
对象的回调方法来实现模拟异步回调操作。ArgumentCaptor
模拟异步步骤:
Mockito doAnswer
doAnswer
方法可以模拟在某个方法被调用时,返回指定的结果。我们在构造返回结果的时候,可以通过invocation
对象获取调用过程中传入的参数。我们利用doAnswer
的这个特点模拟异步操作。doAnswer
模拟异步步骤:
参考资料:
Android 单元测试第六篇(Hamcrest 匹配器)
Testing with Hamcrest
Java Hamcrest Unit testing asynchronous methods with Mockito
Testing Callbacks with Mockito