我在如何測試複雜邏輯的RxJava流中有很多操作符。我發現如果我有複雜的邏輯和許多將複雜邏輯串聯在一起的操作符,那麼測試流的單元就會變成一場噩夢,因爲要覆蓋的案例太多了。如何在RxJava運算符中對複雜邏輯進行單元測試?
這裏是什麼我描述一個例子:
Observable<ObjectA> observable = myRepository
.fetchA()
.flatMap(new Func1<ObjectA, Observable<ObjectA>>() {
@Override
public Observable<ObjectA> call(final ObjectA object) {
if (object.isAvailable()) {
//do something
return myRepository
.fetchAnotherThing();
} else {
//do something else
return myRepositor
.fetchADifferentThing();
}
}
})
.flatMap(new Func1<ObjectA, Observable<ObjectA>>() {
@Override
public Observable<ObjectA> call(final ObjectA object) {
if (object.isFull()) {
//do something
return myRepository
.doThingA();
} else {
//do something else
return myRepository
.doThingB();
}
}
});
如果我要爲此編寫一個單元測試,我需要寫至少4種的測試方法,這樣我可以覆蓋所有組合條件邏輯。
通常當這樣的事情發生時,我會寫一個自定義類來處理邏輯,然後單元測試該類。所以上面的代碼可能會變成這樣:
public class MyFunc implements Func1<ObjectA, Observable<ObjectA>> {
@Override
public Observable<ObjectA> call(final ObjectA object) {
//The logic that was formerly in an anonymous Func1 is now here
if (object.isAvailable()) {
//do something
return myRepository.fetchAnotherThing();
} else {
//do something else
return myRepository.fetchADifferentThing();
}
}
}
public class MyOtherFunc implements Func1<ObjectA, Observable<ObjectA>> {
@Override
public Observable<ObjectA> call(final ObjectA object) {
//The logic that was formerly in an anonymous Func1 is now here
if (object.isFull()) {
//do something
return myRepository.doThingA();
} else {
//do something else
return myRepository.doThingB();
}
}
}
現在MYFUNC和MyOtherFunc現在可以進行單元測試本身,我可以確認的邏輯是孤立正確的。然後,我的原代碼,有可能轉化爲這樣的事:
Observable<ObjectA> observable = myRepository
.fetchA()
.flatMap(myFunc)
.flatMap(myOtherFunc);
這當然看起來更簡潔,減輕了鏈條的我的單元測試來處理很多情況下,像以前那樣的需要,但現在的問題是如何我測試剩下的東西嗎?
如果我嘲笑myFunc和myOtherFunc的輸出,那麼看起來好像我根本沒有測試任何東西。另一種選擇是使用myFunc和myOtherFunc的真實實現,但現在我不再進行單元測試了,我正在進行集成測試,並且帶來了額外的麻煩。
有沒有其他人在此之前就掙扎過,如果是的話,您是如何解決您的可測試性問題的?
如果爲'myFunc'和'myOtherFunc'創建模擬,則可以測試a)時序,b)錯誤條件,c)並行性,d)組合的變化。例如,當'fetchA()'發出多個項目時會發生什麼?沒有相關產品? –