无法在单元测试中模拟服务
再会!我有一项服务,可以在创建方法中观察从数据源收到的流程。
我正在尝试创建单元测试来验证服务是否会存储收到的值。但是当我尝试开始测试时,它会抛出 android.os.Handler 中的方法 postAtFrontOfQueue 未被嘲笑。
完整的异常消息:java.lang.RuntimeException:android.os.Handler 中的方法 postAtFrontOfQueue 未被模拟。有关详细信息,请参阅http://g.co/androidstudio/not-mocked。
您能帮我找出我做错了什么吗?
这是我的服务:
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)
}
}
}
测试类:
@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)
}
}
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)
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如 @Demigod 所示,将行
unitTests.returnDefaultValues = true
添加到您的模块build.gradle
中:as @Demigod indicated, add line
unitTests.returnDefaultValues = true
into your modulebuild.gradle
: