当我测试一个用 编写的简单 db 时Room
,当 dao 函数用suspend
. 错误是:
java.lang.RuntimeException: Delegate runner 'androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner' for AndroidJUnit4 could not be loaded.
我的实体是:
@Entity(indices = [Index(value = ["user_name"], unique = true)])
class User (
@ColumnInfo(name = "user_name") var name: String,
@PrimaryKey(autoGenerate = true) var id: Long = 0
)
如您所见,我想防止数据库存储User
相同的user_name
内容。
我的道课是:
@Dao
interface UserDao {
@Insert
fun insertUser(user: User): Long
@Delete
fun deleteUser(user: User)
}
我的测试是:
@Test fun insertUser() {
val jojo = User("Jojo")
val id = userDao.insertUser(jojo)
Assert.assertNotEquals(null, id)
}
// Inserting the same `User` must raise a `SQLiteConstraintException`
@Test(expected = SQLiteConstraintException::class)
fun insertSameUser() {
val jojo = User("Jojo")
userDao.insertUser(jojo)
userDao.insertUser(jojo)
}
那时,所有测试都按预期成功。
当我将 dao 类更改为使用suspend
函数时会出现问题:
@Dao
interface UserDao {
@Insert
suspend fun insertUser(user: User): Long
@Delete
suspend fun deleteUser(user: User)
}
我将测试更改如下:
@Test fun insertUser()= runBlocking {
val jojo = User("Jojo")
val id = userDao.insertUser(jojo)
Assert.assertNotEquals(null, id)
}
// Inserting the same `User` must raise a `SQLiteConstraintException`
@Test(expected = SQLiteConstraintException::class)
fun insertSameUser() = runBlocking {
val jojo = User("Jojo")
userDao.insertUser(jojo)
userDao.insertUser(jojo)
}
现在测试可暂停功能失败!
ARuntimeException
提出:
java.lang.RuntimeException: Delegate runner 'androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner' for AndroidJUnit4 could not be loaded.
at androidx.test.ext.junit.runners.AndroidJUnit4.throwInitializationError(AndroidJUnit4.java:92)
at androidx.test.ext.junit.runners.AndroidJUnit4.loadRunner(AndroidJUnit4.java:82)
at androidx.test.ext.junit.runners.AndroidJUnit4.loadRunner(AndroidJUnit4.java:51)
at androidx.test.ext.junit.runners.AndroidJUnit4.<init>(AndroidJUnit4.java:46)
at java.lang.reflect.Constructor.newInstance(Native Method)
at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104)
at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86)
at androidx.test.internal.runner.junit4.AndroidAnnotatedBuilder.runnerForClass(AndroidAnnotatedBuilder.java:63)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
at androidx.test.internal.runner.AndroidRunnerBuilder.runnerForClass(AndroidRunnerBuilder.java:153)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at androidx.test.internal.runner.TestLoader.doCreateRunner(TestLoader.java:73)
at androidx.test.internal.runner.TestLoader.getRunnersFor(TestLoader.java:104)
at androidx.test.internal.runner.TestRequestBuilder.build(TestRequestBuilder.java:789)
at androidx.test.runner.AndroidJUnitRunner.buildRequest(AndroidJUnitRunner.java:543)
at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:386)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1959)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance(Native Method)
at androidx.test.ext.junit.runners.AndroidJUnit4.loadRunner(AndroidJUnit4.java:72)
... 16 more
Caused by: org.junit.runners.model.InitializationError
at org.junit.runners.ParentRunner.validate(ParentRunner.java:418)
at org.junit.runners.ParentRunner.<init>(ParentRunner.java:84)
at org.junit.runners.BlockJUnit4ClassRunner.<init>(BlockJUnit4ClassRunner.java:65)
at androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner.<init>(AndroidJUnit4ClassRunner.java:43)
at androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner.<init>(AndroidJUnit4ClassRunner.java:48)
... 18 more
我发现错误来自 test insertSameUser
,如果我insertSameUser
按照以下方式更改,则不再有错误:
@Test(expected = SQLiteConstraintException::class)
fun insertSameUser() = runBlocking {
val jojo = User("Jojo")
userDao.insertUser(jojo)
userDao.insertUser(jojo)
Assert.assertEquals(null, "fake")
}
如果我按照此处@RunWith(AndroidJUnit4::class)
的建议删除, 则测试失败并显示. 如果我再次添加上面的虚拟测试,那么测试就可以工作了。java.lang.Exception: Method insertSameUser() should be void
有人有想法吗?
依赖项是:
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.core:core-ktx:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3'
//Room
def room_version = "2.2.1"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version" // For Kotlin use kapt instead of annotationProcessor
// optional - Kotlin Extensions and Coroutines support for Room
implementation "androidx.room:room-ktx:$room_version"
// Test helpers
testImplementation "androidx.room:room-testing:$room_version"
}