Live Data を使ったコードのテストを記述する場合にはメインスレッドで実行しなければいけない
Live data をUnit Test であれこれする時には、 MainThread で実行しなければいけないという制限が問題になります。
具体的には、 LiveData の setValue
メソッドを呼び出す時には ArchTaskExecutor.getInstance().isMainThread()
を呼び出して現在がメインスレッドで実行されているかの確認を行い、メインスレッドであれば実行するみたいなことをしてます。
Unit Test で実行する場合には、メインスレッドで実行されないため、問題になります。
普通にテスト記述していく場合には、 下記のようにaac の core-testing library に存在する InstantTaskExecutorRule()
をTaskExecuter に当てはめてあげれば実行できるかと認識しています。
@Rule @JvmField val instantTaskExecutorRule = InstantTaskExecutorRule()
Spek で実行する場合の問題点
Spek で Unit Test を記述していく場合の問題点として、「Spek ではSpekのコンストラクタに Lambda を渡し、その中に DSL 等を含みテストコードを記述していく」というものが存在します。
object MyTest: Spek({ group("a group") { test("a test") { ... } group("a nested group") { test("another test") { ... } } } })
仮に書いたとしてもこんな感じで表示される.
Spek で LiveData を利用した時にメインスレッド以外でもテストを実行できるようにする方法
上記で記したように ArchTaskExecutor
というクラスを置き換えることで(?)普通のJUnit でLive Data なクラスを実行する時には実現してます。
実は、 ArchTestExecutor
には、Executor を独自のものに置き換えれるメソッドが生えています。ということでそれを使い実行していけば大丈夫です。
具体的には以下のようなコードで大丈夫です。
beforeEachTest { ArchTaskExecutor .getInstance() .setDelegate(object : TaskExecutor() { override fun executeOnDiskIO(runnable: Runnable) { runnable.run() } override fun isMainThread(): Boolean { return true } override fun postToMainThread(runnable: Runnable) { runnable.run() } }) } afterEachTest { ArchTaskExecutor.getInstance().setDelegate(null) }