记录一下在写repo类的单元测试时遇到的问题
测试框架使用
Robolectric
+Mockito
网络框架:rxjava2
+retrofit2
最初我自己写TestRule
继承ExternalResource
来帮我做一下执行repo单元测试方法之前和之后应该做的事,例如:
1.登陆取获usertoken
2.重置数据库,在`Robolectric`框架下不重置会出现问题
结束时
1.做断言
为什么在结束时做断言?
因为我测试的类是repo,是专门用来与服务器做交互的部分,断言的类型非常单一,都是在一个callback上判断返回的数据,code=200,或者数据非空就行,本来我是这么写的:
var callBack: (Any) -> Unit = {result->
if (result is Resource<*>) {
Assert.assertThat((result as? Resource<*>)?.status, CoreMatchers.`is`(Status.SUCCESS))
} else {
Assert.assertNotNull(result)
}
}
看上去没啥问题但是出现了关键问题1:
这样写assert不会生效
因为assert其实是一个异常,单元测试框架捕获到这个异常,就给你来一个测试不通过
但是这个callback回调是网路请求的,网络请求的结构是最流行的rxjava+retrofit的那一套,这个callback方法在rxjava的方法内
而rxjava的方法是throw Throwable的,assert在callback里是无效的,异常根本报不出来,throw了····
好吧这是来到我们的断言2.0:
var result: Any? = null
var callBack: (Any) -> Unit = {
result = it
}
fun after() {
if (result is Resource<*>) {
Assert.assertThat((result as? Resource<*>)?.status, CoreMatchers.`is`(Status.SUCCESS))
} else {
Assert.assertNotNull(result)
}
}
这个after()
方法就是ExternalResource
的方法,会在每个单元测试的方法执行完执行,这样总行了吧
我跑了一下单元测试大多数都正常了,但是还是出现了一个小问题,我在单独运行一个单元测试方法时一切都是正常的,然后运行一整个单元测试类的时候,断言的错误不会出现在单元测试方法内,而是出现在了after()
方法里,这让我找问题很不好找我以为测试方法里的断言是都过了的···其实没有···害我找我半天问题····
那为什么会这样的?
答案在下面这段代码里,它来自我们的ExternalResource
private Statement statement(final Statement base) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
before();
try {
base.evaluate();
} finally {
after();
}
}
};
}
没错ExternalResource
用try
包裹了我们的测试方法,我不知道为啥···我有点委屈····
但是好在问题找到了,找到了就好解决了,我复制了ExternalResource
里面的全部代码去掉了try
然后让我的RepoTestRule
直接实现TestRule
暂时没发现问题···如果出现新的问题我会及时更新