Home > Net >  Unable to mock service in Unit test
Unable to mock service in Unit test

Time:03-30

Good day! I have a service what observe flow recieved from datasource in on create method.

I'am trying to create unit test to verify if service will store recieved value. But when I try to start test it throw Method postAtFrontOfQueue in android.os.Handler not mocked.

Full exeption message: java.lang.RuntimeException: Method postAtFrontOfQueue in android.os.Handler not mocked. See http://g.co/androidstudio/not-mocked for details.

Can you please help me to figure out what i'm doing wrong?

Here is my service:

override fun onCreate() {
        super.onCreate()

        val onPressIntent = Intent(this, MainActivity::class.java)
        val pendingIntent =
            PendingIntent.getActivity(this, 1, onPressIntent, PendingIntent.FLAG_IMMUTABLE)

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

            val name = getString(R.string.sensor_notification_channel_name)
            val importance = IMPORTANCE_DEFAULT
            val channel = NotificationChannel(SENSOR_CHANNEL_ID, name, importance)
            val manager: NotificationManager =
                getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

            manager.createNotificationChannel(channel)
        }

        val notification = NotificationCompat.Builder(this, SENSOR_CHANNEL_ID)
            .setContentTitle(this.getString(R.string.sensor_notification_tittle))
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentText(getString(R.string.sensor_notification_description))
            .setContentIntent(pendingIntent)
        startForeground(1, notification.build())

        lifecycleScope.launchWhenCreated {
            gravityFluctuationUseCase.deletePreviousValue()
        }

        gravityFluctuationUseCase.getFluctuationsRecord().asLiveData().observe(this){ value ->
            Log.d("TAG", "Sensor event: $value")
            lifecycleScope.launch(dispatcher){
                gravityFluctuationUseCase.addNewItem(value)
            }
        }
    }

Test class:

@ExtendWith(InstantExecutorExtension::class)
class SensorServiceTest : KoinTest {

    private lateinit var useCase: GravityFluctuationUseCase
    private lateinit var service: SensorService
    private val dispatcher = TestCoroutineDispatcher()

    @BeforeEach
    fun setUp() {
        val context: Context = mockk(relaxed = true) {
            every { applicationContext } returns this
        }
        useCase = mockk(relaxed = true)

        startKoin {
            modules(
                module {
                    single { useCase }
                    single { Dispatchers.Default }
                }
            )
        }
        val notificationService: android.app.NotificationManager = mockk(relaxed = true)
        val lifecycle = LifecycleRegistry(mockk(relaxed = true))
        lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_START)
        service = spyk(SensorService()){
            every { applicationContext } returns context
            every { [email protected] } returns lifecycle
            every { getSystemService(Context.NOTIFICATION_SERVICE) } returns notificationService
            every { packageManager } returns mockk(relaxed = true)
        }

        mockkStatic(PendingIntent::class)
        every { PendingIntent.getActivity(any(), any(), any(), any()) } returns mockk(relaxed = true)

        mockkConstructor(NotificationCompat.Builder::class)
        every { anyConstructed<NotificationCompat.Builder>().build() } returns mockk(relaxed = true)

        Dispatchers.setMain(dispatcher)
    }

    @AfterEach
    fun tearDown() {
        stopKoin()
        unmockkConstructor(NotificationCompat.Builder::class)
        unmockkStatic(PendingIntent::class)
        Dispatchers.resetMain()
    }

    @Test
    fun verify_service_adding_new_value_when_receive() {
        val initVal = 1f
        val initFlow = flowOf(initVal)
        val resultList = mutableListOf<Float>()
        coEvery { useCase.getFluctuationsRecord() } returns initFlow
        coEvery { useCase.addNewItem(initVal) }.answers {
            resultList.add(initVal)
        }

        service.onCreate()
        Truth.assertThat(resultList)
            .contains(initVal)
    }
}

CodePudding user response:

as @Demigod indicated, add line unitTests.returnDefaultValues = true into your module build.gradle:

    testOptions {
        unitTests.returnDefaultValues = true // add this
        unitTests.all {
            useJUnitPlatform()
        }
  • Related