Hello, I'm trying to make a Unit Test for this us...
# android
d
Hello, I'm trying to make a Unit Test for this usecase :
Copy code
class PlaySoundUseCase @Inject constructor(
    val context: Context,
    private val dispatchers: DispatcherProvider
) {
    suspend operator fun invoke(
        scope: CoroutineScope, pickingSound: PickingSounds, numberOfTime: Int
    ) {
        scope.launch(dispatchers.main) {
            for (i in 0 until numberOfTime) {
                MediaPlayer.create(
                    context,
                    when (pickingSound) {
                        PickingSounds.QUANTITY_COMPLETE -> R.raw.item_end
                        PickingSounds.VALIDATION -> R.raw.address_end
                        PickingSounds.UNEXPECTED_TAG -> R.raw.error
                        PickingSounds.TOO_MANY_TAGS -> R.raw.error
                        PickingSounds.CONGRATULATIONS -> R.raw.wave_end
                        PickingSounds.EPC_READ -> R.raw.epc_read
                        else -> R.raw.wave_end
                    }
                ).apply {
                    setOnCompletionListener { release() }
                    start()
                }
                delay(50)
            }
        }

    }
}
This usecase work well, but i can t find a solution to test it, this one is particular because i give him a coroutine scope because i want to delay sound when played multiple time. And it seems that create an unit test with coroutine scope is difficult for me I try this test and some variation :
Copy code
@OptIn(ExperimentalCoroutinesApi::class)
class PlaySoundUseCaseTest {
    private lateinit var useCase: PlaySoundUseCase
    private val dispatchers = TestDispatchers()
    val dispatcher = StandardTestDispatcher()
    val scope = TestScope(dispatcher)
    val sound = mockk<MediaPlayer>()

    @Before
    fun setUp() {
        mockkStatic(MediaPlayer::class)
        useCase = PlaySoundUseCase(mockk(), dispatchers)
        coEvery { MediaPlayer.create(any(), any<Int>() ) } returns sound
        coEvery { sound.release() } returns Unit
        coEvery { sound.setOnCompletionListener(any()) } returns Unit
        coEvery { sound.start() } returns Unit
    }

    @Test
    fun `when playing sound, should play multiple sound if asked`() = runTest {
        useCase(scope, PickingSounds.EPC_READ, 2)
        scope.advanceTimeBy(1000)
        coVerify(exactly = 2) { MediaPlayer.create(any(), any<Int>()) }
    }
}
But always got this error Verification failed: call 1 of 1: class android.media.MediaPlayer.create(any(), any())). One matching call found, but needs at least 2 and at most 2 calls Telling me that it s called only once, but in real life it works because i m hearing 2 sound and if i m removing scope.launch and delay, test is working and verify that there is 2 calls So the problem seems to come from the coroutine scope If anyone can help me ^^
m
runTest will provide you with a TestScope, try passing that ro your usecase instead of creating a new one