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.

user1667968
źródło

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()
    
Eugen Martynov
źródło
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
rds
źródło
4
w RoboElectric 3.0 aplikacja Roboelectric już nie istnieje, więc jest to prawdopodobnie najlepsza odpowiedź
kenyee
19

Użyj tego:

Robolectric.application
Xian
źródło
16

Dodaj

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

I użyć:

private val app = ApplicationProvider.getApplicationContext()
Jan
źródło
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.

Marsjanin
źródło
5

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

  1. adnotacja @RunWith (RobolectricTestRunner.class)
  2. RuntimeEnvironment.application.getApplicationContext ()
user1390616
źródło
2

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

Farrukh Najmi
źródło
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).

qix
źródło
2

Najpierw dodaj do swojego build.gradle:

testImplementation 'androidx.test:core:1.2.0'

następnie użyj:

ApplicationProvider.getApplicationContext() as Application

dougie
źródło
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

Kirill Karmazin
źródło
1

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

drspaceboo
źródło
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' }

Bhuro
źródło
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 )

grego
źródło
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
Karoly
źródło