这是 AmamResourceDao. kt 文件的内容:
@Daointerface AlarmResourceDao {
@Query(
value = """
SELECT * FROM alarm_resources
WHERE
is_scheduled = 'T'
ORDER BY id ASC
"""
)fun getAllScheduledAlarmResources(): Flow<List<AlarmResourceEntity>>
@Query(
value = """
SELECT * FROM alarm_resources
WHERE id = :id
"""
)fun getAlarmResource(id: Int): Flow<AlarmResourceEntity>
@Insert(onConflict = OnConflictStrategy.IGNORE)suspend fun insertOrIgnoreAlarmResource(entity: AlarmResourceEntity): Long
}
我正在使用以下 BooleanConverter 将布尔值转换为字符串,反之亦然:
class BooleanConverter {
@TypeConverterfun charToBoolean(value: Char): Boolean {
return when(value?: 'F') {
'T' -> true't' -> trueelse -> false
}
}
@TypeConverterfun booleanToChar(boolean: Boolean): Char {
return when(boolean) {
true -> 'T'false -> 'F'
}
}
}
现在我想测试数据库操作,但以下测试用例总是失败:
class AlarmResourceDaoTest {
private val TAG: String = "Morning Walk Alarm"private lateinit var alarmResourceDao: AlarmResourceDao
private lateinit var db: ScDatabase
@Beforefun createDb() {
val context = ApplicationProvider.getApplicationContext<Context>()
db = Room.inMemoryDatabaseBuilder(
context,
ScDatabase::class.java,
).build()
alarmResourceDao = db.alarmResourceDao()
}
@Testfun alarmResourceDao_fetches_scheduled_alarms_by_ascending_id() = runTest {
val alarmResourceEntities = listOf(
testAlarmResource(
id = 0,
label = "Morning Walk",
scheduledTime = LocalTime.of(5, 0, 0),
isScheduled = true,
),
testAlarmResource(
id = 1,
label = "Lunch",
scheduledTime = LocalTime.of(12, 0, 0),
isScheduled = false,
),
testAlarmResource(
id = 2,
label = "Dinner",
scheduledTime = LocalTime.of(8, 0, 0),
isScheduled = true,
),
testAlarmResource(
id = 3,
label = "Android Development",
scheduledTime = LocalTime.of(9, 0, 0),
isScheduled = false,
)
)
for( alarmResourceEntity in alarmResourceEntities) {
alarmResourceDao.insertOrIgnoreAlarmResource(
alarmResourceEntity
)
}
val morningWalkAlarm = alarmResourceDao.getAlarmResource(0).first()
Log.i(TAG, "Morning Walk Alarm 1: ${morningWalkAlarm.toString()}")
val scheduledAlarmResourceEntities = alarmResourceDao.getAllScheduledAlarmResources()
.first()
Log.i(TAG, "Morning Walk Alarm 2: ${scheduledAlarmResourceEntities[0].toString()}")
assertEquals(
"Morning Walk",
scheduledAlarmResourceEntities[0].label
)
}
}
在测试中,我用 Morning Walk报警
标签记录了两次,但只记录了一次,这是在获取所有计划报警实体之前。
这些是测试运行时的日志:
---------------------------- PROCESS STARTED (17813) for package com.example.clock.core.database ----------------------------
2023-10-24 11:46:19.173 17813-17837 Morning Walk Alarm com.example.clock.core.database I Morning Walk Alarm 1: AlarmResourceEntity(id=0, label=Morning Walk, scheduledTime=05:00, isScheduled=true)
---------------------------- PROCESS ENDED (17813) for package com.example.clock.core.database ----------------------------
这是测试结果:
java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0
at jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
at jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
at jdk.internal.util.Preconditions.checkIndex(Preconditions.java:266)
at java.util.Objects.checkIndex(Objects.java:359)
at java.util.ArrayList.get(ArrayList.java:434)
at com.example.clock.core.database.AlarmResourceDaoTest$alarmResourceDao_fetches_scheduled_alarms_by_ascending_id$1.invokeSuspend(AlarmResourceDaoTest.kt:75)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.test.TestDispatcher.processEvent$kotlinx_coroutines_test(TestDispatcher.kt:28)
at kotlinx.coroutines.test.TestCoroutineScheduler.tryRunNextTaskUnless$kotlinx_coroutines_test(TestCoroutineScheduler.kt:103)
at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt$runTest$2$1$workRunner$1.invokeSuspend(TestBuilders.kt:320)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:280)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:85)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source:1)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source:1)
at kotlinx.coroutines.test.TestBuildersJvmKt.createTestResult(TestBuildersJvm.kt:13)
at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt.runTest-8Mi8wO0(TestBuilders.kt:308)
at kotlinx.coroutines.test.TestBuildersKt.runTest-8Mi8wO0(Unknown Source:1)
at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt.runTest-8Mi8wO0(TestBuilders.kt:166)
at kotlinx.coroutines.test.TestBuildersKt.runTest-8Mi8wO0(Unknown Source:1)
at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt.runTest-8Mi8wO0$default(TestBuilders.kt:158)
at kotlinx.coroutines.test.TestBuildersKt.runTest-8Mi8wO0$default(Unknown Source:1)
at com.example.clock.core.database.AlarmResourceDaoTest.alarmResourceDao_fetches_scheduled_alarms_by_ascending_id(AlarmResourceDaoTest.kt:36)
从测试中,我可以得出结论,插入
和 查询
通过 id
的 AllarmResourceEntity
工作正常,但是当从数据库中获取多个 AlarmResourceEntities
时,问题就出现了。
你能帮我解决这个问题吗?