I am migrating my app to androidx, I can't seem to get my unit tests working. I took example from Google's AndroidJunitRunnerSample, which has been updated to use the new androidx api. I get the following error when trying to run my tests:
java.lang.Exception: Delegate runner 'androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner' for AndroidJUnit4 could not be loaded. Check your build configuration.
Here is my module 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'
}
And here is how my tests are structured:
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
}
What am I doing wrong?
Removing @RunWith(AndroidJUnit4.class)
annotations from the test classes fixed the issue, although I can't really say why or how it fixed it.
Edit: Allright I did some more testing. I migrated my app to Kotlin, and suddenly I noticed the tests began to work with the @RunWith
annotation, too. Here's what I found out:
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....
}
}
This java test fails with the Delegate runner for AndroidJunit4 could not be loaded
error. But If I remove the @RunWith
annotation, it works. Also, if I replace the @BeforeClass
setup with just a @Before
, like this:
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....
}
}
The tests will run without errors. I needed to use the @BeforeClass
annotation, so I just removed @RunWith
.
But now that I am using Kotlin, the following (which should be equal to the first java example) works:
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...
}
}
Also, as Alessandro Biessek said in an answer and @Ioane Sharvadze in the comments, the same error can happen with the @Rule
annotation. If I add a line
@Rule val instantTaskExecutorRule = InstantTaskExecutorRule()
To the Kotlin example, the same delegate runner error happens. This must be replaced with
@get:Rule val instantTaskExecutorRule = InstantTaskExecutorRule()
Explanation here.
You also get the error message if you use a test rule in Kotlin and write it Java style
@Rule
var mainActivityActivityTestRule = ActivityTestRule(MainActivity::class.java)
You have to change @Rule
to @get:Rule
@get:Rule
var mainActivityActivityTestRule = ActivityTestRule(MainActivity::class.java)
The error message displayed when I delete the @Test method.
You can try to put a @Test method and run
@Test
public void signInTest() {
}
Changing
@Test
void someTest() {
// Testing here
}
to
@Test
public void someTest() {
// Testing here
}
works for me.
If after adding the following dependencies:
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'
and
android{
defaultConfig{
...
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
...
}
}
doesn't help then use the deprecated AndroidJUnit4
class which belongs to the androidx.test.runner
package instead of the one belongs to androidx.test.ext.junit.runners.AndroidJUnit4
package.
I still don't understand why AndroidJUnit4
class is deprecated while the Gradle dependencies it belongs to is suggested by the Android team everywhere i.e Codelabs and docs
Maybe you haven't updated the runner on the gradle config file?
defaultConfig {
...
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
Also, AndroidStudio 3.2 has an option to automate the migration of your dependencies to AndroidX (Refactor -> Migrate to AndroidX...) that did that for me.
For me the problem was the @Rule
annotation..
I don't know the cause for now.
As a temporary workaround yo can for example start your activity using UIAutomator for ActivityTestRule.
You can use @JvmField
. From documentation
Instructs the Kotlin compiler not to generate getters/setters for this property and expose it as a field
@Rule
@JvmField
val activityActivityTestRule = ActivityScenarioRule<MainActivity>(MainActivity::class.java)
I gut this error for simply set fun as private, removing this solved this for me.
I fixed with this configuration:
My dependencies:
/*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"
In my defaultConfig
section I have:
defaultConfig {
applicationId "uy.edu.ude.archcomponents"
minSdkVersion 22
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunnerArguments clearPackageData: 'true'
}
In the test I have:
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)
}
}
}
I also use the android plugin version 3.4.2. I took the config from here
Some other possible reasons:
- Having only
@SmallTest
(or Medium-/Large-) test methods. Marking at least one method with@Test
solves the issues. setup()
/teardown()
methods are not public.
来源:https://stackoverflow.com/questions/52873173/migrating-junit4-tests-to-androidx-what-causes-delegate-runner-could-not-be-lo