我正在将应用程序迁移到androidx,但似乎无法使单元测试正常工作。我以Google's AndroidJunitRunnerSample为例,该示例已更新为使用新的androidx api。尝试运行测试时出现以下错误:
java.lang.Exception: Delegate runner 'androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner' for AndroidJUnit4 could not be loaded. Check your build configuration.
这是我的模块build.gradle:
android {
defaultConfig {
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
}
dependencies {
// Test dependencies
androidTestImplementation 'androidx.test:core:1.0.0-beta02'
androidTestImplementation 'androidx.test.ext:junit:1.0.0-beta02'
androidTestImplementation 'androidx.test:runner:1.1.0-beta02'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0-beta02'
androidTestImplementation "androidx.arch.core:core-testing:2.0.0"
androidTestImplementation 'androidx.room:room-testing:2.1.0-alpha01'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0-beta02'
androidTestImplementation 'org.hamcrest:hamcrest-library:1.3'
}
这是我的测试的结构:
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@RunWith(AndroidJUnit4.class)
public class EntityParcelTest {
@BeforeClass
public void createEntities() {
// Setup...
}
@Test
void someTest() {
// Testing here
}
我在做什么错了?
答案 0 :(得分:22)
从测试类中删除@RunWith(AndroidJUnit4.class)
注释可解决此问题,尽管我不能真正说出原因或解决方法。
编辑:好的,我还做了一些测试。我将应用程序迁移到Kotlin,突然间我注意到测试也开始使用@RunWith
批注。这是我发现的:
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@RunWith(AndroidJUnit4.class) // <-- @RunWith + @BeforeClass = Error
public class AndroidXJunitTestJava {
@BeforeClass
public static void setup() {
// Setting up once before all tests
}
@Test
public void testing() {
// Testing....
}
}
此Java测试失败,并显示Delegate runner for AndroidJunit4 could not be loaded
错误。但是,如果我删除@RunWith
批注,它将起作用。另外,如果我仅用@BeforeClass
替换@Before
设置,就像这样:
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@RunWith(AndroidJUnit4.class) // <-- @RunWith + @Before = works?
public class AndroidXJunitTestJava {
@Before
public void setup() {
// Setting up before every test
}
@Test
public void testing() {
// Testing....
}
}
测试将正确运行。我需要使用@BeforeClass
批注,因此我刚刚删除了@RunWith
。
但是现在我正在使用Kotlin,以下方法(应该等于第一个Java示例)有效:
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.BeforeClass
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class AndroidXJunitTest {
companion object {
@BeforeClass fun setup() {
// Setting up
}
}
@Test
fun testing() {
// Testing...
}
}
此外,正如Alessandro Biessek在回答中和@Ioane Sharvadze在评论中说的那样,@Rule
批注可能发生相同的错误。如果我添加一行
@Rule val instantTaskExecutorRule = InstantTaskExecutorRule()
对于Kotlin示例,发生相同的委托运行器错误。必须替换为
@get:Rule val instantTaskExecutorRule = InstantTaskExecutorRule()
说明here。
答案 1 :(得分:10)
如果您在Kotlin中使用测试规则并将其编写为Java样式,也会收到错误消息
@Rule
var mainActivityActivityTestRule = ActivityTestRule(MainActivity::class.java)
您必须将@Rule
更改为@get:Rule
@get:Rule
var mainActivityActivityTestRule = ActivityTestRule(MainActivity::class.java)
答案 2 :(得分:1)
您需要确保所有带有 @BeforeClass 注释的类都是 public static 。例如:
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@RunWith(AndroidJUnit4.class)
public class EntityParcelTest {
@BeforeClass
public static void createEntities() {
// Setup...
}
@Test
public void someTest() {
// Testing here
}
答案 3 :(得分:1)
删除@Test方法时显示的错误消息。
您可以尝试放置@Test方法并运行
@Test
public void signInTest() {
}
答案 4 :(得分:1)
在测试活动时,请确保ActivityTestRule变量是公共的:
@Rule
public ActivityTestRule<YourActivity> activityTestRule = new ActivityTestRule<>(YourActivity.class);
答案 5 :(得分:1)
有两种方法可以尝试解决此问题:
构建->清理项目。然后构建->重建项目
有2个具有AndroidJUnit4的软件包
androidx.test.runner
(已弃用)androidx.test.ext.junit.runners
确保您的build.gradle(应用程序)具有此行
android {
defaultConfig {
....
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
....
}
}
并确保在测试课程之前的@RunWith(AndroidJUnit4.class)
中使用(1)(已弃用)而不是(2)(新的但尚未稳定)。
答案 6 :(得分:0)
就我而言,我跳过了用@Test
进行注释的测试用例。这不是你的情况。这个答案是给像我这样的人的。
答案 7 :(得分:0)
也许您尚未在gradle配置文件上更新跑步者?
defaultConfig {
...
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
此外,AndroidStudio 3.2还提供了一个选项,可以自动将依赖项迁移到AndroidX(重构->迁移到AndroidX ...),这对我来说是有效的。
答案 8 :(得分:0)
AndroidJUnit4 在类和超类中都不支持带有@Test
批注的函数:
@Test fun dontWork(param: String) {}
@Test private fun dontWork2() {}
注意:如果没有@Test
批注,则可以使用以上
一种预期的方式可能是:
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class ClassTest : SuperTest() {
@Test
fun test() {}
private fun allowedWithoutAnnotation(paramAllowed: String) {}
}
defaultConfig {
...
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
dependencies {
...
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
androidTestImplementation 'androidx.arch.core:core-testing:2.1.0'
}
GL
答案 9 :(得分:0)
对于我来说,我通过将所有@Test
,@Before
和@After
方法都声明为public
并声明@BeforeClass
和{{ 1}}为@AfterClass
如果您将这些方法中的任何一个保留为隐式/显式public static
或显式protected
;您将遇到以下异常
private
所以,正确的方法是使用
java.lang.RuntimeException: Delegate runner 'androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner' for AndroidJUnit4 could not be loaded.
代替:
@Before
public void setUp() {
}
@BeforeClass
public static void init() {
}
答案 10 :(得分:0)
就我而言,定义函数参数是问题所在。
@Test
fun foo(string: String = "") { // Causes "Delegate runner could not be loaded" error.
// ...
}
我必须做类似以下的事情。
@Test
fun foo() {
foo("")
}
fun foo(string: String) { // Can be called from other test functions.
// ...
}
答案 11 :(得分:0)
答案 12 :(得分:0)
其他一些可能的原因:
@SmallTest
(或中/大)测试方法。用@Test
标记至少一种方法可以解决问题。setup()
/ teardown()
方法不是公开的。答案 13 :(得分:0)
我使用以下配置进行了修复:
我的依赖项:
/*Instrumentation Test*/
androidTestImplementation "org.assertj:assertj-core:3.12.2"
androidTestImplementation ('androidx.test.espresso:espresso-core:3.2.0',{
exclude group: 'com.android.support', module: 'support-annotations'
})
androidTestImplementation "androidx.arch.core:core-testing:2.1.0-rc01"
在我的defaultConfig
部分,我有:
defaultConfig {
applicationId "uy.edu.ude.archcomponents"
minSdkVersion 22
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunnerArguments clearPackageData: 'true'
}
在测试中,我有:
package uy.edu.ude.archcomponents.repository
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.room.Room
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.runner.AndroidJUnit4
import com.example.android.roomwordssample.WordDao
import com.example.android.roomwordssample.WordRoomDatabase
import kotlinx.coroutines.runBlocking
import org.assertj.core.api.Assertions.assertThat
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import uy.edu.ude.archcomponents.entity.Word
import java.io.IOException
@RunWith(AndroidJUnit4::class)
class WordDaoTest {
@get:Rule
val instantTaskExecutorRule = InstantTaskExecutorRule()
private lateinit var wordDao: WordDao
private lateinit var db: WordRoomDatabase
@Before
fun createDb() {
val context = InstrumentationRegistry.getInstrumentation().context
// Using an in-memory database because the information stored here disappears when the
// process is killed.
db = Room.inMemoryDatabaseBuilder(context, WordRoomDatabase::class.java)
// Allowing main thread queries, just for testing.
.allowMainThreadQueries()
.build()
wordDao = db.wordDao()
}
@After
@Throws(IOException::class)
fun closeDb() {
db.close()
}
@Test
@Throws(Exception::class)
fun insertAndGetWord() {
runBlocking {
val word = Word("word")
wordDao.insert(word)
val allWords = wordDao.getAlphabetizedWords().waitForValue()
assertThat(allWords[0].word).isEqualTo(word.word)
}
}
}
我还使用了Android插件版本3.4.2。我从here
获得了配置答案 14 :(得分:0)
我将这个错误归结为只是将fun设置为private,消除了这个错误,这对我来说就解决了。
答案 15 :(得分:0)
更改
@Test
void someTest() {
// Testing here
}
到
@Test
public void someTest() {
// Testing here
}
为我工作。
答案 16 :(得分:0)
如果在添加以下依赖项之后:
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation
'com.android.support.test.espresso:espresso-core:3.0.1'
和
android{
defaultConfig{
...
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
...
}
}
然后不能使用属于AndroidJUnit4
包的已弃用的androidx.test.runner
类,而不是使用属于androidx.test.ext.junit.runners.AndroidJUnit4
包的类。
答案 17 :(得分:0)
您可以使用@JvmField
。从文档
指示Kotlin编译器不要为此属性生成getter / setter,并将其公开为字段
@Rule
@JvmField
val activityActivityTestRule = ActivityScenarioRule<MainActivity>(MainActivity::class.java)
答案 18 :(得分:0)
对我来说,问题是@Rule
注释。.
我现在不知道原因。
作为一种临时的解决方法,您可以例如使用UIAutomator for ActivityTestRule启动您的活动。