W jaki sposób możemy uzyskać dostęp do kontekstu aplikacji w Robolectric?


112

Właściwie potrzebuję odpowiedzi na wywołanie API, do tego potrzebowałem Context.

Odpowiedzi:


218

Aktualizacja.

Po prostu użyj dla wersji 1.xi 2.x:

Robolectric.application;

A dla wersji 3.x:

RuntimeEnvironment.application;

A dla wersji 4.x:

  • dodaj do swojego build.gradlepliku:

    testImplementation 'androidx.test:core:1.0.0'
    
  • pobierz kontekst za pomocą:

    ApplicationProvider.getApplicationContext()
    

11
Czy umieściłeś @RunWith (RobolectricTestRunner.class) do swoich testów?
Eugen Martynov

4
Tak .. Dodałem ... ale nadal zwraca wartość null
user1667968

1
Zrobiłem wszystko, o czym wspomniałeś, i nadal tracę wartość. Coś jeszcze może mi brakować?
Moises Jimenez

13
Upewnij się również, że nie używasz RuntimeEnvironment.applicationw kodzie statycznym (jak metody z adnotacjami @BeforeClass), ponieważ Robolectric prawdopodobnie nie zostanie zainicjowany w tym momencie, a wartość będzie null.
sfera

1
To również powoduje krwawienie aplikacji między testami ... co może nie być pożądane
Chris

26

Możesz użyć

RuntimeEnvironment.application

4
w RoboElectric 3.0 aplikacja Roboelectric już nie istnieje, więc jest to prawdopodobnie najlepsza odpowiedź
kenyee


16

Dodaj

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

I użyć:

private val app = ApplicationProvider.getApplicationContext()

import androidx.test.core.app.ApplicationProvider
luckyhandler

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

2
To jest prawidłowa odpowiedź w przypadku najnowszego Robolectric. Inne wymienione tutaj metody zostały wycofane lub usunięte.
Gabor

7

Najnowsza wersja Robolectric 4.3 od teraz w 2019 r. ''

ShadowApplication.getInstance ()

`i

Aplikacja Roboletric

oboje są pozbawieni praw. Więc używam

Context context = RuntimeEnvironment.systemContext;

aby uzyskać Context.


5

Aby uzyskać kontekst aplikacji, wykonaj następujące czynności:

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

2

To działa dla mnie z Robolectric 3.5.1: ShadowApplication.getInstance().applicationContext


Zauważ, że wygląda na to, że wersja 4.0 usunie tę metodę; lepiej się trzymaćRuntimeEnvironment.application lub RuntimeEnvironment.application.getApplicationContext()jeśli to działa dla Ciebie.
qix

2

Od wydania 4.0-alpha-3 21 lipca zostały one usunięte ShadowApplication.getApplicationContext() . Trzymaj się RuntimeEnvironment.application.getApplicationContext()wszelkich testów z adnotacją @RunWith(RobolectricTestRunner::class).

Na marginesie, ich obecny przewodnik zawiera przykład pobierania zasobów ciągów za pomocą:

final Context context = RuntimeEnvironment.application;

(Zauważ, że javadocs dla RuntimeEnvironmenti ShadowApplicationobecnie odzwierciedlają wersję inną niż alfa 3.x).


2

Najpierw dodaj do swojego build.gradle:

testImplementation 'androidx.test:core:1.2.0'

następnie użyj:

ApplicationProvider.getApplicationContext() as Application


2

W niektórych przypadkach może być potrzebny kontekst aplikacji zamiast domyślnego kontekstu Robolectris. Na przykład, jeśli chcesz uzyskać nazwę swojego pakietu. Domyślnie Robolectric zwróci Ci org.robolectric.defaultnazwę pakietu. Aby uzyskać prawdziwą nazwę pakietu, wykonaj następujące czynności:

build.gradle

testImplementation 'org.robolectric:robolectric:4.2.1'

Twoja klasa testowa:

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

}

Upewnij się, że w katalogu roboczym Run / Debug Configurations ustawiono: $ MODULE_DIR $ wprowadź opis obrazu tutaj wprowadź opis obrazu tutaj


1

Bezpieczniej jest używać Robolectric.getShadowApplication()zamiast Robolectric.applicationbezpośrednio.


Ale co, jeśli potrzebuję dostępu do niektórych niestandardowych właściwości mojej niestandardowej aplikacji? Wygląda na to, że nie mogę pobrać prawdziwego obiektu z aplikacji cienia.
Denis Kniazhev

@DenisKniazhev Przepraszam, że nie mogę ci odpowiedzieć. Wkrótce po tym, jak zaczęliśmy używać Robolectric, zaczęliśmy używać Travisa jako naszego CI, a one nie grają dobrze. Domyślam się, że możesz przesłać go do swojej aplikacji lub możesz potrzebować stworzyć niestandardowego runnera, aby uzyskać do niego dostęp w ten sposób. Powodzenia
drspaceboo

Dzięki, na razie właśnie utknąłemRobolectric.application
Denis Kniazhev

6
Robolectric.getShadowApplication () jest niedostępny
IgorGanapolsky

1

Zgadzam się z odpowiedziami @EugenMartynov i @rds ....

Szybki przykład można znaleźć w Volley-Marshmallow-Release

w NetworkImageViewTest.java

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

Link do Volleya jest dostępny https://android.googlesource.com/platform/frameworks/volley/+/marshmallow-release

musisz dodać zależności w module volley w Android Studio jako:

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


1

W twoim przypadku myślę, że powinieneś uważać na to, co tak naprawdę testujesz. Czasami napotkanie problemów z niesprawdzalnym kodem lub pozornie niesprawnym kodem jest oznaką, że być może twój kod wymaga refaktoryzacji.

W przypadku odpowiedzi na wywołanie interfejsu API możesz nie chcieć testować samego wywołania interfejsu API. Może nie być konieczne testowanie, czy możliwe jest wysyłanie / odbieranie informacji z dowolnej usługi internetowej, ale raczej to, że kod obsługuje i przetwarza odpowiedź w oczekiwany sposób.

W takim przypadku lepiej byłoby zrefaktoryzować kod, który próbujesz przetestować. Podziel analizę / obsługę odpowiedzi na inną klasę, która akceptuje proste Stringi przeprowadź testy na tej klasie , wstrzykując przykładowe odpowiedzi w postaci ciągów.

Jest to mniej więcej zgodne z ideami Single Responsibility and Dependency Inversion (The S i D w SOLID )


1

Ok, więc wiem, że wielu innych powiedziało tę odpowiedź wcześniej i może już być nieaktualna

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

Otrzymałem wartość null, ponieważ część when () była PO inicjalizacji sut. To może pomóc niektórym z was.

też mam

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

na początku zajęć

Również

 when(mockApplication.getApplicationContext()).thenReturn(RuntimeEnvironment.application.getApplicationContext()); works
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.