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()
}