LoginSignup
0
0

More than 3 years have passed since last update.

MockRetrofit で異常系のテストを行う時の注意

Posted at

TL;DR

MockRetrofit で異常系のテストを行う時は、 例外を throw せずに、 BehaviorDelegate#returning にエラー内容を渡す。

※例外を throw すると、UnitTest が中断されてしまいます。

Good

class MockGitHubService(
    private val delegate: BehaviorDelegate<GitHubService>
) : GitHubService {

    override fun listRepos(user: String): Observable<List<Repository>> {
        // 通信失敗を delegate する
        val fakeCall = Calls.response(Response.error<Repository>(404, ResponseBody.create(...)))
        return delegate.returning(fakeCall).listRepos(user)
    }
}

Bad

class MockGitHubService(
    private val delegate: BehaviorDelegate<GitHubService>
) : GitHubService {

    override fun listRepos(user: String): Observable<List<Repository>> {
        // ここで throw すると、UnitTest の実行が中断される
        throw HttpException(Response.error<List<Repository>>(404, ResponseBody.create(...)))
    }
}

背景

  • API の呼び出しを Retrofit & RxJava で行っている
  • 特定の例外なら、成功に丸め込んだり、別の例外を投げ直す

という事を行っており、正常系・異常系の UnitTest を書こうとしていました。

サンプルでおなじみの、GitHub API の呼び出しのコードで書くと、

service.listRepos("octocat")
    .onErrorReturn { throwable ->
        when {
            // 404 なら空 list を返す(成功扱いにする)
            (throwable is HttpException && throwable.code() == 404) -> listOf()
            else -> throw throwable
        }
    }

こんなイメージで、これがテスト対象です。

正常系の MockService が、

override fun listRepos(user: String): Observable<List<Repository>> {
    val fakeResponse = listOf(Repository(...), Repository(...)) // 2 件返す
    return delegate.returningResponse(fakeResponse).listRepos(user)
}

のように記述できるので、 fun listRepos で throw したら、 onErrorReturn にひっかかる と思い込んでました。。。

(テストコードの全体感は、正常系のサンプルが色々出てくるのでそちらを参照下さい。)

まとめ

MockRetrofit で異常系のテストを行う時は、 例外を throw せずに、 BehaviorDelegate#returning にエラー内容を渡す。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0