question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Setting LiveData within FunSpec

See original GitHub issue

Using Kotest 4.3.1

I’m in the process of attempting to migrate my tests within an Android app to use FunSpec, and I cannot work out how to set a value on MutableLiveData<> when testing my ViewModel after migration.

With:

class ProductDetailsViewModel (private val myRepository: MyRepository) : ViewModel() {
    // Exposed to UI
    val productName = MutableLiveData<String>()

    // ...
}

I can successfully test with:

@ExtendWith(InstantTaskExecutorExtension::class)
@TestInstance(TestInstance.Lifecycle.PER_METHOD)
class ProductDetailsViewModelTest{
    private val dataSourceMock = mockk<ProductRepository>(relaxed = true)

    private val td = ProductTestData()

    @Test
    fun `DetailsViewModel minimal` () {
        val vm = ProductDetailsViewModel(dataSourceMock)

        vm.productName.value = td.minimalTestProduct.productName
        true shouldBe true  // Nonsense test to get a pass
    }
}

I have tried to migrate this to FunSpec as follows:

@ExtendWith(InstantTaskExecutorExtension::class)
@TestInstance(TestInstance.Lifecycle.PER_METHOD)
class ProductDetailsViewModelTest : FunSpec({
    val dataSourceMock = mockk<ProductRepository>(relaxed = true)

    val td = ProductTestData()

    val vm = ProductDetailsViewModel(dataSourceMock)

    test("DetailsViewModel minimal") {
        vm.productName.value = td.minimalTestProduct.productName

        true shouldBe true // Nonsense test to get a pass
    }

And this gives an exception, which I think is because the InstantTaskExecutorExtension isn’t being applied via the FunSepc:

android/os/Looper
java.lang.NoClassDefFoundError: android/os/Looper
	at androidx.arch.core.executor.DefaultTaskExecutor.isMainThread(DefaultTaskExecutor.java:77)
	at androidx.arch.core.executor.ArchTaskExecutor.isMainThread(ArchTaskExecutor.java:116)
	at androidx.lifecycle.LiveData.assertMainThread(LiveData.java:461)
	at androidx.lifecycle.LiveData.setValue(LiveData.java:304)
	at androidx.lifecycle.MutableLiveData.setValue(MutableLiveData.java:50)

Is there a way to do what I am trying to do? Or should I just stick with ‘standard’ Junit5 tests when trying to work with LiveData?

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:5

github_iconTop GitHub Comments

2reactions
aids61517commented, Dec 11, 2020

You should create a ProjectConfig like this

object ProjectConfig : AbstractProjectConfig() {
  private val testDispatcher = TestCoroutineDispatcher()

  override fun beforeAll() {
    super.beforeAll()
    setupLiveData()
    //setup whatever you want
  }

  override fun afterAll() {
    super.afterAll()
    resetLiveData()
  }

  private fun setupLiveData() {
    ArchTaskExecutor.getInstance().setDelegate(object : TaskExecutor() {
      override fun executeOnDiskIO(runnable: Runnable) {
        runnable.run()
      }

      override fun postToMainThread(runnable: Runnable) {
        runnable.run()
      }

      override fun isMainThread(): Boolean {
        return true
      }
    })
  }

  private fun resetLiveData() {
    ArchTaskExecutor.getInstance().setDelegate(null)
  }
}
0reactions
stale[bot]commented, Feb 13, 2021

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to write unit test for the method returns LiveData with ...
First create the extension methods for LiveData. ... wait indefinitely if the LiveData is not set. if (!latch.await(time, timeUnit)) { this.
Read more >
LiveData overview - Android Developers
Use LiveData to handle data in a lifecycle-aware fashion. ... Create LiveData objects; Observe LiveData objects; Update LiveData objects ...
Read more >
Unit Test your LiveData and ViewModel | by Murat Can Bur
The ViewModel class is designed to store and manage UI-related data so that the data survives configuration changes such as screen rotations. If ......
Read more >
How to easily test a ViewModel with LiveData and Coroutines
In line 35, we call the method in ViewModel class that will set the value to the LiveData. Then we observe to it...
Read more >
Testing LiveData in JUnit 4 and JUnit 5 - Jeroen Mols
set a delegate before each test that updates live data values immediately on the calling thread · remove the delegate after each tests...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found