Kotlin — Part 9:单元测试与 Kotlin(Mockito,RxJava)

让我们谈谈在 Kotlin 中使用单元测试,我没有提及为什么我们需要创建单元测试,我们都知道测试在开发中是非常重要的部分,所以今天我们添加一些单元测试到我们的 App 中,这集中在我们的 NewsManager 类,负责请求,映射 Reddit 新闻数据,主要是网络连接问题.

全部章节:

Kotlin — Part 0:关于这个系列
Kotlin — Part 1:配置 Android Studio
Kotlin — Part 2:语法,空安全,静态类型
Kotlin — Part 3:扩展函数、Android 扩展、委托属性
Kotlin — Part 4:RecyclerView— Kotlin 适配器委托&数据类
Kotlin — Part 5:Kotlin,RxJava&RxAndroid
Kotlin — Part 6:API-Retrofit&Kotlin)
Kotlin — Part 7:无限滑动:高阶函数& Lambdas
Kotlin — Part 8:方向改变(序列化&数据类)
Kotlin — Part 9:单元测试与 Kotlin(Mockito,RxJava)

Github 仓库:https://github.com/imuhao/KedditBySteps

NewsApi 接口

为了使单元测试简单,我们为新闻 Api 创建了一个新接口,现在我通过这个接口模拟数据.这个接口没有什么不同的,所以我们调到下一个部分.

NewsManager 单元测试

我们需要配置项目,为 NewsManager 创建单元测试

Mockito 依赖

Mockito是一个惊人的扩展,使单元测试非常简单,你可以在 Kotlin 中使用它.

1
testCompile "org.mockito:mockito-core:2.+"

如果你尝试模拟一个带有泛型的类,如 模拟 Retrofit Call 类, 它将不会工作,你可以使用扩展函数使它工作正常.

1
inline fun <reified T : Any> mock(): T = Mockito.mock(T::class.java)

现在它将允许我们这样做:

1
var callMock = mock<Call<RedditNewsResponse>>()

现在我们已经准备好了

使用 TestSubscriber 测试 Observable

一个简单的方法测试 observables 是使用 RxJava 提供的 TestSubscriber 类.它将允许你运行一个 Observable 与一些断言

1
2
3
4
5
var testSub = TestSubscriber<RedditNews>()
newsManager.getNews("").subscribe(testSub)
testSub.assertNoErrors()
testSub.assertValueCount(1)
testSub.assertCompleted()

Commit:单元测试

请在这个 Commit 中查看所有的代码详情

https://github.com/imuhao/KedditBySteps/commit/69a7a0591973dc4ffc5fd0885f61d649c6bf61c5

一个完整的单元测试像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Test
fun testSuccess_basic() {
// prepare
val redditNewsResponse = RedditNewsResponse(RedditDataResponse(listOf(), null, null))
val response = Response.success(redditNewsResponse)

`when`(callMock.execute()).thenReturn(response)

// call
val newsManager = NewsManager(apiMock)
newsManager.getNews("").subscribe(testSub)

// assert
testSub.assertNoErrors()
testSub.assertValueCount(1)
testSub.assertCompleted()
}

在 Android Studio 中预览