Obtenir le contexte du projet de test dans le cas de test Junit Android


108

Quelqu'un sait-il comment obtenir le contexte du projet de test dans le cas de test junit Android (étend AndroidTestCase).

Remarque: le test n'est PAS un test d'instrumentation.

Remarque 2: j'ai besoin du contexte du projet de test, pas du contexte de l'application réelle qui est testée.

J'en ai besoin pour charger certains fichiers à partir des actifs du projet de test.


Pourquoi ne pouvez-vous pas simplement utiliser InstrumentationTestCase?
yorkw

1
Parce que je teste des services, pas une interface utilisateur.
peceps

1
Il y a une meilleure réponse trouvée ici: [Utilisation d'AndroidTestCase au lieu d'un test JUnit] [1] [1]: stackoverflow.com/questions/3170706/...
Jaime Botero

Réponses:


137

Il existe une nouvelle approche avec la bibliothèque de support de test Android (actuellement androidx.test:runner:1.1.1). Exemple mis à jour de Kotlin:

class ExampleInstrumentedTest {

    lateinit var instrumentationContext: Context

    @Before
    fun setup() {
        instrumentationContext = InstrumentationRegistry.getInstrumentation().context
    }

    @Test
    fun someTest() {
        TODO()
    }
}

Si vous souhaitez également exécuter le contexte d'application:

InstrumentationRegistry.getInstrumentation().targetContext

Exemple d'exécution complet: https://github.com/fada21/AndroidTestContextExample

Regardez ici: Quelle est la différence entre getTargetContext () et getContext (sur InstrumentationRegistry)?


1
Enfin une réponse sur la façon d'utiliser JUnit4 avec InstrumentationTest. Après des heures de recherche. Je dois aimer le développement Android.
Fabian Zeindl le

1
Agréable! tx (notez qu'il y a une faute de frappe dans votre membre de la classe)
Greg

1
Quelqu'un pourrait-il vous aider sur les dépendances à ajouter dans le fichier gradle pour que cela fonctionne?
Greg

1
N'oubliez pas d'ajouter compile "com.android.support.test:runner:1.0.1"à votre note
egorikem

2
Il est obsolète, utilisez à la InstrumentationRegistry.getInstrumentation().contextplace.
Allan Veloso

37

Après quelques recherches, la seule solution de travail semble être celle déjà indiquée par Yorkw. Vous devrez étendre InstrumentationTestCase, puis vous pourrez accéder au contexte de votre application de test en utilisant getInstrumentation (). GetContext () - voici un bref extrait de code utilisant les suggestions ci-dessus:

public class PrintoutPullParserTest extends InstrumentationTestCase {

    public void testParsing() throws Exception {
        PrintoutPullParser parser = new PrintoutPullParser();
        parser.parse(getInstrumentation().getContext().getResources().getXml(R.xml.printer_configuration));
    }
}

7
Oui mais il semble idiot qu'Android ne donne pas accès au contexte du projet de test dans de simples tests JUnit. Le contexte est là dans AndroidTestCase.mTestContext mais il est privé. Je ne vois pas pourquoi.
peceps

@peceps Full Ack - mais c'est comme ça et je ne l'aime pas non plus;)
AgentKnopf

25

Comme vous pouvez le lire dans le code source d'AndroidTestCase , la getTestContext()méthode est masquée.

/**
 * @hide
 */
public Context getTestContext() {
    return mTestContext;
}

Vous pouvez contourner l' @hideannotation en utilisant la réflexion.

Ajoutez simplement la méthode suivante dans votre AndroidTestCase:

/**
 * @return The {@link Context} of the test project.
 */
private Context getTestContext()
{
    try
    {
        Method getTestContext = ServiceTestCase.class.getMethod("getTestContext");
        return (Context) getTestContext.invoke(this);
    }
    catch (final Exception exception)
    {
        exception.printStackTrace();
        return null;
    }
}

Ensuite, appelez à getTestContext()tout moment. :)


2
Cela a parfaitement fonctionné pour moi et je charge des actifs en utilisant Context soit AndroidTestCase via cette méthode, soit ActivityInstrumentationTestCase2.getInstrumentation () .getContext () puis getResources () .getAssets ()
Andrew Mackenzie

Pouvez-vous spéculer sur les raisons pour lesquelles ils l'ont caché? Si nous utilisons cette technique, pourraient-ils supprimer la méthode dans une version ultérieure (brisant notre code de test)?
Andrew Shepherd

1
Je reçoisjava.lang.NoSuchMethodException: android.test.ServiceTestCase.getTestContext()
kurdtpage

4

Mise à jour: AndroidTestCase cette classe est obsolète au niveau de l'API 24. À utiliser à la InstrumentationRegistryplace. Les nouveaux tests doivent être écrits à l'aide de la bibliothèque de support des tests Android. Lien vers l'annonce

Vous devez étendre AndroidTestCase au lieu de TestCase.

Vue d'ensemble de la classe AndroidTestCase
Étendez ceci si vous avez besoin d'accéder à des ressources ou à d'autres éléments qui dépendent du contexte d'activité.

AndroidTestCase - Développeurs Android


4

Si vous souhaitez obtenir le contexte avec Kotlin et Mockito, vous pouvez le faire de la manière suivante:

val context = mock(Context::class.java)

J'espère que ça vous aide


obtenir null en contexte?
Deven

Et n'oubliez pas d'annoter votre classe de test avec @RunWith (MockitoJUnitRunner :: class)
USMAN osman

2

Il s'agit de la manière correcte d'obtenir le contexte. D'autres méthodes sont déjà obsolètes

import androidx.test.platform.app.InstrumentationRegistry

InstrumentationRegistry.getInstrumentation().context

2
import androidx.test.core.app.ApplicationProvider;

    private Context context = ApplicationProvider.getApplicationContext();

1

Pour ceux qui rencontrent ces problèmes lors de la création de tests automatisés, vous devez faire ceci:

    Context instrumentationContext;

    @Before
    public void method() {

        instrumentationContext = InstrumentationRegistry.getInstrumentation().getContext();

        MultiDex.install(instrumentationContext);
    }

0

Les autres réponses sont dépassées. À l'heure actuelle, chaque fois que vous étendez AndroidTestCase, il existe un objet mContext Context que vous pouvez utiliser.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.