記錄一下在寫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
暫時沒發現問題···如果出現新的問題我會及時更新