Comment accéder au contexte d'une application dans Robolectric?


112

En fait, j'ai besoin d'obtenir une réponse à un appel API, pour cela, j'avais besoin Context.

Réponses:


218

Mettre à jour.

Utilisez simplement pour les versions 1.x et 2.x:

Robolectric.application;

Et pour la version 3.x:

RuntimeEnvironment.application;

Et pour la version 4.x:

  • ajouter à votre build.gradledossier:

    testImplementation 'androidx.test:core:1.0.0'
    
  • récupérer le contexte avec:

    ApplicationProvider.getApplicationContext()
    

11
Avez-vous mis @RunWith (RobolectricTestRunner.class) pour vos tests?
Eugen Martynov

4
Ouais .. J'ai ajouté ... mais il renvoie toujours null
user1667968

1
J'ai fait tout ce que vous avez mentionné et je suis toujours nul. Y a-t-il autre chose que je pourrais manquer?
Moises Jimenez

13
Assurez-vous également que vous n'utilisez pas RuntimeEnvironment.applicationde code statique (comme les méthodes annotées avec @BeforeClass) car Robolectric ne sera probablement pas initialisé à ce stade et la valeur le sera null.
sfera

1
Cela provoque également un saignement de l'application entre les tests .. ce qui n'est peut-être pas souhaitable
Chris

26

Vous pouvez utiliser

RuntimeEnvironment.application

4
dans RoboElectric 3.0, Roboelectric.application n'existe plus, c'est donc probablement la meilleure réponse
kenyee


16

Ajouter

testImplementation "androidx.test:core-ktx:${deps.testrunner}"

Et utilise:

private val app = ApplicationProvider.getApplicationContext()

import androidx.test.core.app.ApplicationProvider
luckyhandler

val appContext = ApplicationProvider.getApplicationContext <Context> ()
luckyhandler

2
C'est la bonne réponse avec le dernier Robolectric. Les autres méthodes mentionnées ici sont obsolètes ou supprimées.
Gabor

7

Pour le dernier Robolectric 4.3 dès maintenant en 2019 `

ShadowApplication.getInstance ()

`et

Roboletric.application

sont tous deux dépréciés. Alors j'utilise

Context context = RuntimeEnvironment.systemContext;

pour obtenir le contexte.


5

Pour obtenir le contexte de l'application, vous devez effectuer les opérations suivantes:

  1. annoter @RunWith (RobolectricTestRunner.class)
  2. RuntimeEnvironment.application.getApplicationContext ()

2

Cela fonctionne pour moi avec Robolectric 3.5.1: ShadowApplication.getInstance().applicationContext


Notez qu'il semble que la version 4.0 supprimera cette méthode; mieux de s'en tenir RuntimeEnvironment.applicationou RuntimeEnvironment.application.getApplicationContext()si cela fonctionne pour vous.
qix

2

Depuis la version 4.0-alpha-3 du 21 juillet, ils ont été supprimés ShadowApplication.getApplicationContext() . Restez fidèle à RuntimeEnvironment.application.getApplicationContext()tous les tests annotés avec @RunWith(RobolectricTestRunner::class).

En passant, leur guide actuel a un exemple d'obtention de ressources de chaîne en utilisant:

final Context context = RuntimeEnvironment.application;

(Notez que les javadocs pour RuntimeEnvironmentet ShadowApplicationreflètent actuellement la version non alpha 3.x.)


2

Ajoutez d'abord les éléments suivants à votre build.gradle:

testImplementation 'androidx.test:core:1.2.0'

puis utilisez:

ApplicationProvider.getApplicationContext() as Application


2

Dans certains cas, vous pouvez avoir besoin du contexte de votre application au lieu du contexte par défaut de Robolectris. Par exemple, si vous souhaitez obtenir le nom de votre package. Par défaut, Robolectric vous renverra le org.robolectric.defaultnom de votre package. Pour obtenir votre vrai nom de package, procédez comme suit:

build.gradle

testImplementation 'org.robolectric:robolectric:4.2.1'

Votre classe de test:

@RunWith(RobolectricTestRunner.class)
@Config( manifest="AndroidManifest.xml")
public class FooTest {

@Test
public void fooTestWithPackageName(){
    Context context = ApplicationProvider.getApplicationContext();
    System.out.println("My Real Package Name: " + context.getPackageName());
}

}

Assurez-vous que dans votre répertoire de travail Run / Debug Configurations est défini sur: $ MODULE_DIR $ entrez la description de l'image ici entrez la description de l'image ici


1

Il est plus sûr d'utiliser Robolectric.getShadowApplication()au lieu d'utiliser Robolectric.applicationdirectement.


Mais que faire si j'ai besoin d'accéder à certaines propriétés personnalisées de mon application personnalisée? Il semble que je ne puisse pas obtenir l'objet réel de l'application shadow.
Denis Kniazhev

@DenisKniazhev Désolé, je ne peux pas vous répondre. Peu de temps après avoir commencé à utiliser Robolectric, nous avons commencé à utiliser Travis comme CI, et ils ne jouent pas bien. Je suppose que vous pouvez le diffuser dans votre application ou vous devrez peut-être créer un coureur personnalisé pour y accéder de cette façon.
Bonne

Merci, pour l'instant, je viens de Robolectric.application
m'en tenir

6
Robolectric.getShadowApplication () n'est pas disponible
IgorGanapolsky

1

D'accord avec les réponses de @EugenMartynov et @rds ....

Un exemple rapide peut être trouvé à Volley-Marshmallow-Release

dans NetworkImageViewTest.java

// mNIV = new NetworkImageView(Robolectric.application); mNIV = new NetworkImageView(RuntimeEnvironment.application);

Le lien Volley est disponible https://android.googlesource.com/platform/frameworks/volley/+/marshmallow-release

vous devez ajouter des dépendances dans le module volley dans android studio comme:

dependencies { testCompile 'junit:junit:4.12' testCompile 'org.mockito:mockito-core:1.10.19' testCompile 'org.robolectric:robolectric:3.1.2' }


1

Dans votre cas, je pense que vous devriez être conscient de ce que vous testez réellement. Parfois, rencontrer des problèmes de code non testable ou de code apparemment non testable est un signe que votre code doit peut-être être remanié.

Pour une réponse à un appel API, vous ne souhaiterez peut-être pas tester l'appel API lui-même. Il n'est peut-être pas nécessaire de tester qu'il est possible d'envoyer / recevoir des informations à partir de n'importe quel service Web arbitraire, mais plutôt que votre code gère et traite votre réponse d'une manière attendue.

Dans ce cas, il peut être préférable de refactoriser le code que vous essayez de tester. Répartissez l'analyse / la gestion des réponses dans une autre classe qui accepte un simple Stringet effectuez vos tests sur cette classe en injectant des exemples de réponses de chaîne.

Cela suit plus ou moins les idées de responsabilité unique et d' inversion de dépendance (le S et le D dans SOLID )


1

Ok, donc je sais que beaucoup d'autres ont déjà dit cette réponse et sont peut-être déjà obsolètes

    when(mockApplication.getApplicationContext()).thenReturn(RuntimeEnvironment.application);
    when(mockApplication.getFilesDir()).thenReturn(RuntimeEnvironment.application.getFilesDir());

    sharedPref = RuntimeEnvironment.application.getSharedPreferences(KEY_MY_PREF, Context.MODE_PRIVATE);
    sut = new BundleManagerImpl(mockApplication,
            processHtmlBundle, resultListener, sharedPref);

J'ai obtenu null, car la partie when () était APRÈS l'initialisation de la sut. Cela pourrait aider certains d'entre vous.

aussi j'ai le

@RunWith(CustomRobolectricTestRunner.class)
@Config(constants = BuildConfig.class)

au début du cours

Aussi

 when(mockApplication.getApplicationContext()).thenReturn(RuntimeEnvironment.application.getApplicationContext()); works
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.