用于测试 rxjava 的书面单元测试,但不确定我的单元测试是不是正在测试所有内容
Posted
技术标签:
【中文标题】用于测试 rxjava 的书面单元测试,但不确定我的单元测试是不是正在测试所有内容【英文标题】:Written unit test for testing rxjava, but not sure if my unit test is testing everything用于测试 rxjava 的书面单元测试,但不确定我的单元测试是否正在测试所有内容 【发布时间】:2019-05-25 12:09:37 【问题描述】:android Studio 3.4
我正在测试以下方法。基本上,这个测试所做的是发出一个请求,这将返回一个LoginResponseEntity
,该LoginResponseEntity
将被映射并返回一个Single<LoginResponse>
override fun loginUserPost(username: String, password: String, uniqueIdentifier: String, deviceToken: String, apiToken: String) : Single<LoginResponse>
val loginRequestEntity = LoginRequestEntity(username, password, uniqueIdentifier, deviceToken)
return loginAPIService.loginUserPost(loginRequestEntity, apiToken)
.map
loginResponseDomainMapper.map(it)
我写的测试用例有效,但我认为这并没有完全测试这种方法。
@Test
fun `should return LoginResponse`()
val loginRequestEntity = LoginRequestEntity("username", "password", "uniqueidentifier", "devicetoken")
val loginResponse = LoginResponse("token", createUser(), emptyList(), emptyList())
val loginResponseEntity = LoginResponseEntity("token", createUserEntity(), emptyList(), emptyList())
whenever(loginAPIService.loginUserPost(loginRequestEntity, "apitoken")).thenReturn(Single.just(loginResponseEntity))
loginServiceImp.loginUserPost("username", "password", "uniqueidentifier", "devicetoken", "apitoken")
.test()
.assertValue(loginResponse)
verify(loginAPIService).loginUserPost(loginRequestEntity, "apitoken")
private fun createUser() =
User(
"id",
"email",
"firstname",
"lastname",
"phone",
"address",
"dob",
"customer",
listOf("enterpriseids"),
listOf("vendorids"))
private fun createUserEntity() =
UserEntity(
"id",
"email",
"firstname",
"lastname",
"phone",
"address",
"dob",
"customer",
listOf("enterpriseids"),
listOf("vendorids"))
我还能做些什么来测试这个方法。我应该测试这个方法的.maploginResponseDomainMapper.map(it)
部分吗?
【问题讨论】:
通常你首先测试的是函数的结果。您可以使用 TestScheduler 来做到这一点 除非您使用某种代码覆盖率工具,否则您永远不会知道您的代码是否经过全面测试,您可以尝试jacoco
甚至idea
包含一个
你只是在测试快乐的道路。如果loginAPIService.loginUserPost()
方法失败了怎么办?
【参考方案1】:
这是一个非常小的方法,不包含很多要测试的东西。两个外部依赖项(loginAPIService
和 loginResponseDomainMapper
)减少了更多需要测试的东西。
所以,
1) loginResponseDomainMapper
不是测试方法的一部分,也应该被模拟。
2) 你必须明白,这里应该测试什么。
首先:检查LoginRequestEntity
是否正确构造并传递给loginUserPost
方法。这是通过verify(loginAPIService).loginUserPost(loginRequestEntity, "apitoken")
调用完成的。此外,您可以使用ArgumentCaptor
。
第二:loginUserPost
方法的输出已正确传递给loginResponseDomainMapper.map
方法。这可以像以前一样通过额外的verify
调用来完成。
第三:map方法的输出正确返回。这是通过assertValue
调用完成的。
因此,您只是在尝试验证数据流是否正确,并且在执行过程中外星人或类似的东西没有修改任何内容。
3) 负面测试。也没有多少事情会出错。如果loginUserPost
没有@NotNull
注解,你最好处理null
这个函数的结果。
另外,如果请求不正确怎么办?密码错误,或apitoken
已过期?我相信这不会导致悲惨的后果,但你应该考虑一下。
【讨论】:
【参考方案2】:您可以为不成功的场景添加测试:
1)如果loginUserPost
失败,可以添加:
whenever(loginAPIService.loginUserPost(any(), any())).thenReturn(Single.error(Exception()))
...
.test()
.assertError(...)
2)如果loginResponseDomainMapper
失败,可以添加:
whenever(loginResponseDomainMapper.map(any())).thenThrow(Exception())
...
.test()
.assertError(...)
这样您就可以测试不成功/成功的映射和函数输出,而无需详细说明。 loginResponseDomainMapper
行为应在其自身的单元测试范围内进行测试。
【讨论】:
以上是关于用于测试 rxjava 的书面单元测试,但不确定我的单元测试是不是正在测试所有内容的主要内容,如果未能解决你的问题,请参考以下文章
在RxJava的doOnSuccess运算符中调用了单元测试验证方法