将Junit4测试迁移到androidx:是什么导致';无法加载代理运行程序';?
我正在将我的应用程序迁移到androidx,我的单元测试似乎无法正常工作。我以中的示例为例,它已更新为使用新的androidx api。尝试运行测试时出现以下错误:将Junit4测试迁移到androidx:是什么导致';无法加载代理运行程序';?,android,junit,junit4,androidx,Android,Junit,Junit4,Androidx,我正在将我的应用程序迁移到androidx,我的单元测试似乎无法正常工作。我以中的示例为例,它已更新为使用新的androidx api。尝试运行测试时出现以下错误: java.lang.Exception: Delegate runner 'androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner' for AndroidJUnit4 could not be loaded. Check your build configurat
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
}
我做错了什么?也许您没有更新gradle配置文件中的跑步者
defaultConfig {
...
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
另外,AndroidStudio 3.2还提供了一个选项,可以自动将依赖项迁移到AndroidX(重构->迁移到AndroidX…),我就是这么做的 从测试类中删除@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....
}
}
测试将无错误地运行。我需要使用@BeforeClass
注释,所以我刚刚删除了@RunWith
但是现在我正在使用Kotlin,下面的内容(应该与第一个java示例相同)可以工作:
此外,正如在回答和评论中所说的,@Ioane Sharvadze,@Rule
注释也可能发生同样的错误。如果我加一行
@Rule val instantTaskExecutorRule = InstantTaskExecutorRule()
对于Kotlin示例,同样的委托运行程序错误也会发生。这必须被替换为
@get:Rule val instantTaskExecutorRule = InstantTaskExecutorRule()
解释。对我来说,问题在于
@规则
注释。我现在不知道原因
例如,作为临时解决方法,您可以使用UIAutomator for ActivityTestRule启动您的活动 您可以使用
@JvmField
。从文件
指示Kotlin编译器不为此属性生成getter/setter并将其作为字段公开
@规则
@JvmField
val activityActivityTestRule=ActivityScenarioRule(MainActivity::class.java)
如果在Kotlin中使用测试规则并以Java风格编写,则也会收到错误消息
@Rule
var mainActivityActivityTestRule = ActivityTestRule(MainActivity::class.java)
您必须将@Rule
更改为@get:Rule
@get:Rule
var mainActivityActivityTestRule = ActivityTestRule(MainActivity::class.java)
如果在添加以下依赖项之后:
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'
及
然后使用不推荐使用的AndroidJUnit4
类,该类属于androidx.test.runner
包,而不是属于androidx.test.ext.junit.runners.AndroidJUnit4
包
我仍然不明白为什么
AndroidJUnit4
类被弃用,而它所属的Gradle依赖项是由Android团队建议的,即删除@Test方法时显示的错误消息
您可以尝试放置@Test方法并运行
@Test
public void signInTest() {
}
改变
@Test
void someTest() {
// Testing here
}
到
对我有效。我排除了这个错误,只需将fun设置为private,删除它就可以解决这个问题。我修复了这个配置: 我的依赖项:
/*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。我从中获取了配置,还有其他一些可能的原因:
- 只有
(或中/大)测试方法。使用@SmallTest
标记至少一种方法可以解决问题@Test
/setup()
方法不是公共的teardown()
(已弃用)androidx.test.runner
androidx.test.ext.junit.runners
确保您的build.gradle(应用程序)具有此行
- 测试框架实际上提供的信息太少。我遇到了同样的问题,深入研究了堆栈跟踪,发现了以下验证:
因此您必须在类之前声明
@BeforeClass
方法static
有两种方法可以尝试解决此问题:
解决方案1:
生成-->清理项目。然后构建-->重建项目
解决方案2:
有两个包具有AndroidJUnit4的版本
android {
defaultConfig {
....
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
....
}
}
并确保在测试类之前在
@RunWith(AndroidJUnit4.class)
中使用(1)(已弃用)而不是(2)(新的但还不稳定)。至于我的情况,定义函数参数是个问题
@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.
// ...
}
测试活动时,请确保ActivityTestRule变量是公共的:
@Rule
public ActivityTestRule<YourActivity> activityTestRule = new ActivityTestRule<>(YourActivity.class);
@规则
public ActivityTestRule ActivityTestRule=新的ActivityTestRule(YourActivity.class);
在我的例子中,我通过显式地将所有@Test
、
和
方法声明为public
,并将@AfterClass
方法声明为public static
如果您将这些方法中的任何一个保留为隐式/显式受保护
,或显式私有
;您将遇到以下异常
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() {
}
而不是:
@Before
void setUp() {
}
@Before
protected void setUp() {
}
@Before
private void setUp() {
}
@BeforeClass
public void init() {
}
AndroidJUnit4在类或超类中都不支持带有
@Test
注释的函数中:
- 参数:
@Test-fun-dontWork(param:String){}
- 私有访问修饰符:
@testprivate-fun-dontWork2(){}
@Test
注释,则允许进行上述操作
预期的方式可以是: ClassTest.kt build.gradle(:mobile)
GL您需要确保任何标有@BeforeClass注释的类都是公共静态的。例如:
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
}
在我的例子中,我跳过了用
@test
注释测试用例。这不是你的情况。这个答案适用于像我这样的其他人。似乎我已经在build.gradle中设置了TestInstrumentRunner,并且我也完成了“迁移到AndroidX”重构。但现在,测试是JUnit测试。对我来说,问题是我使用的是@Rule
而不是@get:Rule
一个
@Rule
public ActivityTestRule<YourActivity> activityTestRule = new ActivityTestRule<>(YourActivity.class);
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() {
}
@Before
void setUp() {
}
@Before
protected void setUp() {
}
@Before
private void setUp() {
}
@BeforeClass
public void init() {
}
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'
}
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
}