在上一篇呼叫WebAPI的範例,我們使用了Rxjava,這一篇要再深入介紹在使用Rxjava時應該怎麼測試。
當我們遇到一個外部相依的回傳值為Observable時,直接使用Single.just
或Observable.just
即可。
@Test
fun getDataTest() {
val repository = Mockito.mock(IRepository::class.java)
`when`(repository.getSingleString()).thenReturn(Single.just("Test"))
val presenter = Presenter(repository)
presenter.getSomeBoolean()
Assert.assertEquals("Test Plus", presenter.someString)
}
如果要測試一個Observable,可以使用blockingGet
來取得發射的結果。
@Test
fun getDataTest() {
val singleString = Repository().getSingleString()
val expected = "Test"
val actual = singleString.blockingGet()
Assert.assertEquals(expected, actual)
}
也可以使用TestObserver
的方式來測試。TestObserver 比起blockingGet的作法有更多的功能。
@Test
fun getDataTest2() {
val singleString = Repository().getSingleString()
val testObserver = TestObserver<String>()
singleString.subscribe(testObserver)
testObserver.assertResult("Test")
}
測試多個值的發射。
@Test
fun test(){
val testObserver = TestObserver<String>()
Observable.just("a", "b", "c")
.subscribe(testObserver)
testObserver.assertValues("a", "b", "c" )
}
測試是否完成
testObserver.assertComplete()
測試數量
testObserver.assertValueCount(2)
我們經常會使用Schedulers在io
執行緒與MainThread
切換處理不一樣的事,在單元測試就會因為在不同的執行緒而產生錯誤。
java.lang.RuntimeException: Method getMainLooper in android.os.Looper not mocked.
@Test
fun testScheduler(){
val testObserver = TestObserver<String>()
Single.just("1")
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(testObserver)
testObserver.assertResult("1")
}
解決的方式是在單元測試的時候使用 Schedulers.trampoline()
。建立一個 ISchedulerProvider,用注入的方式讓Schedulers在執行單元測試時都是Schedulers.trampoline()
。
interface ISchedulerProvider {
fun computation() = Schedulers.trampoline()
fun mainThread() = Schedulers.trampoline()
fun io() = Schedulers.trampoline()
}
class SchedulerProvider :ISchedulerProvider{
override fun computation() = Schedulers.computation()
override fun mainThread() = AndroidSchedulers.mainThread()
override fun io() = Schedulers.io()
}
class TrampolineSchedulerProvider :ISchedulerProvider{
override fun computation() = Schedulers.computation()
override fun mainThread() = Schedulers.trampoline()
override fun io() = Schedulers.trampoline()
}
測試時使用TrampolineSchedulerProvider
@Test
fun testScheduler(){
val testObserver = TestObserver<String>()
val schedulerProvider = TrampolineSchedulerProvider()
Single.just("1")
.subscribeOn(schedulerProvider.io())
.observeOn(schedulerProvider.mainThread())
.subscribe(testObserver)
testObserver.assertResult("1")
}
範例下載:
https://github.com/evanchen76/RxjavaUnitTestSample