Je migre mon application vers androidx, je n'arrive pas à faire fonctionner mes tests unitaires. J'ai pris l'exemple de Google AndroidJunitRunnerSample , de Google, qui a été mis à jour pour utiliser la nouvelle API Android. Je reçois le message d'erreur suivant lorsque j'essaie d'exécuter mes tests:
Java.lang.Exception: Delegate runner 'androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner' for AndroidJUnit4 could not be loaded. Check your build configuration.
Voici mon 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'
}
Et voici comment mes tests sont structurés:
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
}
Qu'est-ce que je fais mal?
Le fait de supprimer les annotations @RunWith(AndroidJUnit4.class)
des classes de test a résolu le problème, bien que je ne puisse pas vraiment dire pourquoi ni comment il a résolu le problème.
Edit: D'accord, j'ai fait d'autres tests. J'ai migré mon application vers Kotlin et, tout à coup, j'ai remarqué que les tests commençaient également à fonctionner avec l'annotation @RunWith
. Voici ce que j'ai découvert:
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....
}
}
Ce test Java échoue avec l'erreur Delegate runner for AndroidJunit4 could not be loaded
. Mais si je supprime l'annotation @RunWith
, cela fonctionne. De plus, si je remplace la configuration @BeforeClass
par une simple @Before
, comme ceci:
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....
}
}
Les tests se dérouleront sans erreur. J'avais besoin d'utiliser l'annotation @BeforeClass
, alors je viens de supprimer @RunWith
.
Mais maintenant que j'utilise Kotlin, voici ce qui fonctionne (ce qui devrait être égal au premier exemple 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...
}
}
Aussi, comme Alessandro Biessek a déclaré dans une réponse et @Ioane Sharvadze dans les commentaires, la même erreur peut se produire avec l'annotation @Rule
. Si j'ajoute une ligne
@Rule val instantTaskExecutorRule = InstantTaskExecutorRule()
Pour l'exemple Kotlin, la même erreur de participant délégué se produit. Ceci doit être remplacé par
@get:Rule val instantTaskExecutorRule = InstantTaskExecutorRule()
Explication ici .
Vous pouvez utiliser @JvmField
. De la documentation
Ordonne au compilateur Kotlin de ne pas générer de getters/setters pour cette propriété ni de l'exposer sous forme de champ
@Rule
@JvmField
val activityActivityTestRule = ActivityScenarioRule<MainActivity>(MainActivity::class.Java)
Vous obtenez également le message d'erreur si vous utilisez une règle de test dans Kotlin et l'écrivez en style Java.
@Rule
var mainActivityActivityTestRule = ActivityTestRule(MainActivity::class.Java)
Vous devez changer @Rule
en @get:Rule
@get:Rule
var mainActivityActivityTestRule = ActivityTestRule(MainActivity::class.Java)
Pour moi, le problème était l'annotation @Rule
..
Je ne connais pas la cause pour le moment.
En guise de solution temporaire, vous pouvez par exemple démarrer votre activité avec UIAutomator for ActivityTestRule.
Peut-être n'avez-vous pas mis à jour le coureur dans le fichier de configuration de Gradle?
defaultConfig {
...
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
En outre, AndroidStudio 3.2 a une option pour automatiser la migration de vos dépendances vers AndroidX (Refactor -> Migration vers AndroidX ...) qui l’a fait pour moi.