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.

user1667968
la source

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()
    
Eugen Martynov
la source
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
rds
la source
4
dans RoboElectric 3.0, Roboelectric.application n'existe plus, c'est donc probablement la meilleure réponse
kenyee
19

Utilisez ceci:

Robolectric.application
Xian
la source
16

Ajouter

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

Et utilise:

private val app = ApplicationProvider.getApplicationContext()
John
la source
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.

Le Martien
la source
5

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

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

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

Farrukh Najmi
la source
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.)

qix
la source
2

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

testImplementation 'androidx.test:core:1.2.0'

puis utilisez:

ApplicationProvider.getApplicationContext() as Application

dougie
la source
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

Kirill Karmazin
la source
1

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

drspaceboo
la source
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' }

Bhuro
la source
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 )

Grego
la source
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
Karoly
la source