I am trying to migrate from LiveData to Flow in my Room Dao. App is working fine, but I have problems with testing behavior. When I run the test it is starting and running indefinately. I also tried to use kotlinx.coroutines.test runBlockingTest, but I had issue with "This job has not finished yet" like here. Can someone point me in right direction how to test behavior of my CoresDao?
@Dao
interface CoresDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertCores(cores: List<Core>)
@Transaction
suspend fun replaceCoresData(cores: List<Core>) {
deleteAllCores()
insertCores(cores)
}
@Query("SELECT * FROM cores_table")
fun getAllCores(): Flow<List<Core>>
@Query("DELETE FROM cores_table")
suspend fun deleteAllCores()
}
@RunWith(AndroidJUnit4::class)
class CoresDaoTest {
private lateinit var database: SpaceDatabase
private lateinit var coresDao: CoresDao
private val testDispatcher = TestCoroutineDispatcher()
private val testCoresList = listOf(core2, core3, core1)
@get:Rule
var instantTaskExecutorRule = InstantTaskExecutorRule()
@Before
fun setup() {
Dispatchers.setMain(testDispatcher)
val context = InstrumentationRegistry.getInstrumentation().targetContext
database = Room.inMemoryDatabaseBuilder(context, SpaceDatabase::class.java).build()
coresDao = database.coresDao()
}
@After
fun cleanup() {
database.close()
Dispatchers.resetMain()
testDispatcher.cleanupTestCoroutines()
}
@Test
fun testGetAllCores(): Unit = runBlocking {
withContext(Dispatchers.Main) {
runBlocking { coresDao.insertCores(testCoresList) }
val coresList = mutableListOf<Core>()
coresDao.getAllCores().collect { cores -> coresList.addAll(cores) }
assertThat(coresList.size, equalTo(testCoresList.size))
}
}
}
Kotlin Flow is one of the latest addition to the Kotlin Coroutines. With Kotlin Flow we can handle streams of data asynchronously which is being executed sequentially.
StateFlow, Flow, and LiveData Both are observable data holder classes, and both follow a similar pattern when used in your app architecture. Note, however, that StateFlow and LiveData do behave differently: StateFlow requires an initial state to be passed in to the constructor, while LiveData does not.
To test Flow, the best APIs I found are .take(n).toList()
. You can use runBlockingTest
and you shouldn't need to use withContext
to move the execution to another thread.
You can find an example of how it works here: https://github.com/manuelvicnt/MathCoroutinesFlow/blob/master/app/src/test/java/com/manuelvicnt/coroutinesflow/fibonacci/impl/NeverEndingFibonacciProducerTest.kt#L38
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With