RxJavaでFlowableを返すメソッドのテストの書き方について
概要
RxJavaのFlowableを返して尚且つそれぞれ開始・成功・失敗時に別々の値を返すメソッドのテストを書きたいのですが、テストコード上では開始時の結果しか取得できないため成功と失敗時のテストが出来なくて困っています。
この場合、どのようなテストコードが適切かどなたかご教示いただけるとありがたいです。
使用環境
- AndroidStudio3.3.2
- spek1.1.5
- mockk1.9.3
- RxJava2.2.3
現時点でわかっていること
- 開始時の結果しか取れない。
- 調べた資料では
awaitTerminalEvent
で 「onCompleted()
もしくはonError()
が呼ばれるまで待つ」 とあったが、使用するとテストが終了しない。 - テストコードにて引数を指定して onNext() を使用すると成功時の値は取れるがテストとして意味を成さない
テスト結果
java.lang.AssertionError: Values at position 0 differ; Expected: Success(data=[TaskList(id=1, name=todo, tasks=[Task(id=1, name=aaaaa, status=DONE), Task(id=2, name=aaaaa, status=TODO), Task(id=2, name=aaaaa, status=TODO), Task(id=2, name=aaaaa, status=TODO), Task(id=3, name=aaaaa, status=TODO)])]) (class: Success), Actual: Progress(value=true) (class: Progress) (latch = 1, values = 1, errors = 0, completions = 0, timeout!, disposed!)
実装コード
fun getTaskLists(): Flowable<Result<List<TaskList>>> {
// repository.loadTaskListAndTasksByDB()の結果はモックしている
return repository.loadTaskListAndTasksByDB()
.map {
TaskListTranslator.toTodoLists(it)
}
.toFlowable()
.compose { item ->
item
.map { Result.success(it) } // 成功
.onErrorReturn { Result.failure(it) } // 失敗
.startWith(Result.progress()) // 開始
.subscribeOn(schedulerProvider.io())
.observeOn(schedulerProvider.ui())
}
}
※ toFlowable以下の行は実際には拡張関数にしています。
- https://github.com/syo-sa1982/ToDo4Android/blob/new/usecase/app/src/main/kotlin/com/syousa1982/todo4android/domain/usecase/ToDoUseCase.kt
- https://github.com/syo-sa1982/ToDo4Android/blob/new/usecase/app/src/main/kotlin/com/syousa1982/todo4android/util/extention/ResultRxExt.kt
テストコード
@RunWith(JUnitPlatform::class)
class ToDoUseCaseSpec : Spek({
val taskListRepository: ITaskListRepository by lazy {
mockk<ITaskListRepository>()
}
val schedulerProvider = TestSchedulerProvider()
val todoUseCase: ToDoUseCase by lazy {
ToDoUseCase(taskListRepository, schedulerProvider)
}
// repository.loadTaskListAndTasksByDB()の結果をモック
every { taskListRepository.loadTaskListAndTasksByDB() } answers {
val taskListAndTasks = TaskListAndTasks()
taskListAndTasks.taskList = TaskListEntity(1, "todo")
taskListAndTasks.tasks = listOf(
TaskEntity(1, 1, "aaaaa", Task.Status.DONE.value.toLowerCase()),
TaskEntity(2, 1, "aaaaa", Task.Status.TODO.value.toLowerCase()),
TaskEntity(3, 1, "aaaaa", Task.Status.TODO.value.toLowerCase())
)
Single.create {
listOf(taskListAndTasks)
}
}
describe("ToDoUseCase") {
val expectedValue = Result.success(listOf(
TaskList(1, "todo", listOf(
Task(1, "aaaaa", Task.Status.DONE),
Task(2, "aaaaa", Task.Status.TODO),
Task(3, "aaaaa", Task.Status.TODO)
))
))
// ここで期待値と比較しているが、Result.Progress()しか取れないためテストが通らない
todoUseCase
.getTaskLists()
.test()
.assertValue(expectedValue)
}
})