Come possiamo accedere al contesto di un'applicazione in Robolectric?


112

In realtà, ho bisogno di ottenere una risposta a una chiamata API, per questo ho richiesto Context.

Risposte:


218

Aggiornare.

Basta usare per la versione 1.xe 2.x:

Robolectric.application;

E per la versione 3.x:

RuntimeEnvironment.application;

E per la versione 4.x:

  • aggiungi al tuo build.gradlefile:

    testImplementation 'androidx.test:core:1.0.0'
    
  • recuperare il contesto con:

    ApplicationProvider.getApplicationContext()
    

11
Hai messo @RunWith (RobolectricTestRunner.class) per i tuoi test?
Eugen Martynov

4
Sì .. ho aggiunto ... ma ancora restituisce null
user1667968

1
Ho fatto tutto quello che hai menzionato e continuo a essere nullo. Qualcos'altro che potrei perdere?
Moises Jimenez,

13
Assicurati anche di non utilizzare RuntimeEnvironment.applicationcodice statico (come i metodi annotati con @BeforeClass) poiché Robolectric probabilmente non verrà inizializzato a quel punto e il valore sarà null.
sfera

1
Anche questo fa sì che l'applicazione sanguini tra i test .. il che potrebbe non essere desiderabile
Chris

26

Puoi usare

RuntimeEnvironment.application

4
in RoboElectric 3.0, Roboelectric.application non esiste più, quindi questa è probabilmente la risposta migliore
Kenyee,

19

Usa questo:

Robolectric.application

16

Inserisci

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

E usa:

private val app = ApplicationProvider.getApplicationContext()

importa androidx.test.core.app.ApplicationProvider
luckyhandler

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

2
Questa è la risposta corretta con l'ultimo Robolectric. Altri metodi qui menzionati sono deprecati o rimossi.
Gabor

7

Per l'ultimo Robolectric 4.3 a partire da adesso nel 2019 `

ShadowApplication.getInstance ()

`e

Roboletric.application

sono entrambi deprecati. Quindi sto usando

Context context = RuntimeEnvironment.systemContext;

per ottenere Context.


5

Per ottenere il contesto dell'applicazione è necessario eseguire le seguenti operazioni:

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

2

Questo funziona per me con Robolectric 3.5.1: ShadowApplication.getInstance().applicationContext


Nota che sembra che la versione 4.0 rimuoverà questo metodo; meglio restare RuntimeEnvironment.applicationo RuntimeEnvironment.application.getApplicationContext()se funziona per te.
qix

2

A partire dalla versione 4.0-alpha-3 del 21 luglio, hanno rimosso ShadowApplication.getApplicationContext() . Attenersi a RuntimeEnvironment.application.getApplicationContext()per qualsiasi test annotato con @RunWith(RobolectricTestRunner::class).

Per inciso, la loro guida attuale ha un esempio di come ottenere risorse di stringa utilizzando:

final Context context = RuntimeEnvironment.application;

(Tieni presente che i javadoc per RuntimeEnvironmente ShadowApplicationattualmente riflettono la versione non alpha 3.x.)


2

Per prima cosa aggiungi quanto segue al tuo build.gradle:

testImplementation 'androidx.test:core:1.2.0'

quindi usa:

ApplicationProvider.getApplicationContext() as Application


2

In alcuni casi, potresti aver bisogno del contesto della tua app invece del contesto predefinito di Robolectris. Ad esempio, se vuoi ottenere il nome del tuo pacchetto. Per impostazione predefinita, Robolectric ti restituiràorg.robolectric.default nome del pacchetto. Per ottenere il nome reale del tuo pacchetto, procedi come segue:

build.gradle

testImplementation 'org.robolectric:robolectric:4.2.1'

La tua lezione di prova:

@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());
}

}

Assicurati che nella tua directory di lavoro Run / Debug Configurations sia impostata su: $ MODULE_DIR $ inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine


1

È più sicuro da usare Robolectric.getShadowApplication()invece di usare Robolectric.applicationdirettamente.


Ma cosa succede se ho bisogno di accedere ad alcune proprietà personalizzate della mia applicazione personalizzata? Sembra che non riesca a ottenere l'oggetto reale dall'applicazione shadow.
Denis Kniazhev

@DenisKniazhev Mi dispiace di non poterti rispondere. Poco dopo aver iniziato a utilizzare Robolectric, abbiamo iniziato a utilizzare Travis come CI e non funzionano bene. La mia ipotesi è che tu possa trasmetterlo alla tua applicazione o potresti dover creare un corridore personalizzato per accedervi in ​​questo modo.
Buona

Grazie, per ora mi sono Robolectric.application
limitato

6
Robolectric.getShadowApplication () non è disponibile
IgorGanapolsky

1

D'accordo con le risposte di @EugenMartynov e @rds ....

Un rapido esempio può essere trovato su Volley-Marshmallow-Release

in NetworkImageViewTest.java

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

Il link Volley è disponibile https://android.googlesource.com/platform/frameworks/volley/+/marshmallow-release

devi aggiungere le dipendenze nel modulo volley in Android Studio come:

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


1

Nel tuo caso, penso che dovresti essere consapevole di ciò che stai effettivamente testando. A volte incorrere in problemi di non verificabile codice o il codice apparentemente non verificabile è un segno che forse il vostro codice deve essere riscritta.

Per una risposta alla chiamata API potresti non voler testare la chiamata API stessa. Potrebbe non essere necessario verificare che sia possibile inviare / ricevere informazioni da qualsiasi servizio Web arbitrario, ma piuttosto che il codice gestisce ed elabora la risposta in un maniero previsto.

In tal caso potrebbe essere meglio rifattorizzare il codice che stai tentando di testare. Suddividi la risposta analizzando / gestendo un'altra classe che accetta un semplice Stringed esegui il test su quella classe iniettando risposte di stringa di esempio.

Questo è più o meno seguendo le idee di Single Responsibility and Dependency Inversion (The S and D in SOLID )


1

Ok, quindi so che molti altri hanno già detto questa risposta e potrebbero già essere obsoleti

    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);

Ho ottenuto null, perché la parte when () era DOPO l'inizializzazione di sut. Potrebbe aiutare alcuni di voi.

anche io ho il file

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

all'inizio della lezione

Anche

 when(mockApplication.getApplicationContext()).thenReturn(RuntimeEnvironment.application.getApplicationContext()); works
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.