jUnit4 - Почему при тестировании приостанавливаемой функции возникает ошибка RuntimeException: ... AndroidJUnit4 не может быть загружен?
Когда я тестирую простой БД, написанный с 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)
}
Теперь проверка приостанавливаемых функций не удалась!
А RuntimeException
Поднялся:
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
Я обнаружил, что ошибка возникает из-за теста 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"
}