https://kotlinlang.org logo
Title
z

ziv kesten

03/15/2022, 3:45 PM
I am trying to test a class that is a
CoroutineScope
and is testing a flow emitted from a fake implementation of another class. However, the flow does not seem to emit the data i assign it to stream. What would you think the problem might be?
private val mainThreadSurrogate = newSingleThreadContext("UI thread")

    @Before
    fun setUp() {
        Dispatchers.setMain(mainThreadSurrogate)
    }

    @After
    fun tearDown() {
        Dispatchers.resetMain() // reset the main dispatcher to the original Main dispatcher
        mainThreadSurrogate.close()
    }

    @Test
    fun testTest(): Unit = runBlocking {
        launch(Dispatchers.Main) {
            val recorder = FakeRecordingsHandler()
            val sut = SomeClass(recorder, this.coroutineContext)
            recorder.currentTrack = flow { emit(DEMO_TRACK) }
            val isCurrentTrack = sut.isCurrentTrack(DEMO_TRACK.id)
            assertTrue(isCurrentTrack)
        }
    }
//    class SomeClass(
//        private val recorder: RecordingsHandler,
//        override val coroutineContext: CoroutineContext
//    ) : VoiceRecorder, CoroutineScope {
//
//        private var currentTrackId: String? by mutableStateOf(null)
//
//        init {
//            launch {
//                recorder.currentTrack.distinctUntilChanged().collect { demoTrack ->
//                    currentTrackId = demoTrack?.id
//            }
//         }
//
//        override fun isCurrentTrack(id: String) = currentTrackId == id
//    }
n

Nick Allen

03/15/2022, 3:55 PM
You are collecting from
currentTrack
in
SomeClass
construction, before
currentTrack
is re-assigned. Try assigning first. If you want to control when the item is emitted, then you can emit into a MutableShareFlow (I'd recommend that anyways).
z

ziv kesten

03/16/2022, 7:54 AM
Unfortunatly that does not seem to work as well, i tried with
MutableSharedFlow
and
MutableStateFlow
as well. Also Tried using
runTest { }
the init block is called but the the code inside launch block is not.
@Test
    fun testTest(): Unit = runTest {
        //launch(Dispatchers.Main) {
            val recorder = FakeRecordingsHandler()
            recorder.currentTrack = MutableStateFlow(DEMO_TRACK)
            val sut = VoiceRecorderViewModel(recorder, this.coroutineContext)
            val isCurrentTrack = sut.isCurrentTrack(DEMO_TRACK.id)
            assertTrue(isCurrentTrack)
       // }
    }
Ok so i tried collecting using
GlobalScope
just to verify, and that seemed to work so i guess the problem is the coroutineScope passed to
SomeClass
n

Nick Allen

03/16/2022, 5:51 PM
The default dispatcher of
runTest
does not immediately run scheduled coroutine work. You'll want to call
runCurrent
before verifying so that the
launch
code inside
init
actually starts.