Spek: Android LiveData testing @Rule InstantTaskExecutorRule

Created on 27 Nov 2017  路  3Comments  路  Source: spekframework/spek

hey guys,

how do I use
@Rule val rule = InstantTaskExecutorRule()

inside spek to swaps the background executor.
I am trying to test MutableLiveData, but running into java.lang.RuntimeException: Method getMainLooper in android.os.Looper not mocked when liveData.setValue us called
https://medium.com/@veniosg/unit-testing-with-mutablelivedata-22b3283a7819

ps: very new to spek
please help!

Most helpful comment

I ran into this as well and as @artem-zinnatullin pointed out its fairly easy to achieve:

        // In order to test LiveData, the `InstantTaskExecutorRule` rule needs to be applied via JUnit.
        // As we are running it with Spek, the "rule" will be implemented in this way instead
        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) }

All 3 comments

i am getting @Rule annotation is not allowed to target local variable when I use it inside spek

Rule is a JUnit concept.

Unfortunately, generic Rule interface is designed to wrap test case and decorate it with some behavior without exposing methods like before() and after() (only ExternalResource rule does that by default) that could be called from Spek's beforeEachTest and afterEachTest.

Spek provides all necessary callbacks to decorate tests, but generic Rule just not designed in a way to be used like that.

However, Rule is just bunch of code that runs before and after the test, so you should be able to extract/copy it from Rule and apply it in beforeEachTest {} / afterEachTest {} inside Spek!

I ran into this as well and as @artem-zinnatullin pointed out its fairly easy to achieve:

        // In order to test LiveData, the `InstantTaskExecutorRule` rule needs to be applied via JUnit.
        // As we are running it with Spek, the "rule" will be implemented in this way instead
        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) }
Was this page helpful?
0 / 5 - 0 ratings