Uzyskaj kontekst projektu testowego w przypadku testowym junit systemu Android

108

Czy ktoś wie, jak można uzyskać kontekst projektu testowego w przypadku testu junit systemu Android (rozszerza AndroidTestCase).

Uwaga: test NIE jest testem oprzyrządowania.

Uwaga 2: Potrzebuję kontekstu projektu testowego, a nie kontekstu rzeczywistej testowanej aplikacji.

Potrzebuję tego, aby załadować niektóre pliki z zasobów z projektu testowego.

peceps
źródło
Dlaczego nie możesz po prostu użyć InstrumentationTestCase?
yorkw
1
Ponieważ testuję usługi, a nie interfejs użytkownika.
peceps
1
Tutaj znajduje się lepsza odpowiedź: [Korzystanie z AndroidTestCase zamiast testu JUnit] [1] [1]: stackoverflow.com/questions/3170706/…
Jaime Botero

Odpowiedzi:

137

Jest nowe podejście z biblioteką wsparcia testowania Androida (obecnie androidx.test:runner:1.1.1). Zaktualizowany przykład Kotlin:

class ExampleInstrumentedTest {

    lateinit var instrumentationContext: Context

    @Before
    fun setup() {
        instrumentationContext = InstrumentationRegistry.getInstrumentation().context
    }

    @Test
    fun someTest() {
        TODO()
    }
}

Jeśli chcesz również uruchomić kontekst aplikacji:

InstrumentationRegistry.getInstrumentation().targetContext

Pełny przykład działania: https://github.com/fada21/AndroidTestContextExample

Spójrz tutaj: Jaka jest różnica między getTargetContext () i getContext (w InstrumentationRegistry)?

fada21
źródło
1
Na koniec odpowiedź, jak używać JUnit4 z InstrumentationTest. Po godzinach poszukiwań. Uwielbiam programowanie na Androida.
Fabian Zeindl,
1
Miły! tx (zauważ, że w twojej klasie jest literówka)
Greg
1
Czy ktoś mógłby pomóc, jakie zależności należy dodać w pliku gradle, aby to zadziałało?
Greg
1
Nie zapomnij dodać compile "com.android.support.test:runner:1.0.1"do swojego gradle
egorikem
2
Jest przestarzały, użyj InstrumentationRegistry.getInstrumentation().contextzamiast niego.
Allan Veloso
37

Po kilku badaniach wydaje się, że jedynym działającym rozwiązaniem jest to, na które wskazał już york. Musiałbyś rozszerzyć InstrumentationTestCase, a następnie możesz uzyskać dostęp do kontekstu swojej aplikacji testowej za pomocą metody getInstrumentation (). GetContext () - tutaj jest krótki fragment kodu wykorzystujący powyższe sugestie:

public class PrintoutPullParserTest extends InstrumentationTestCase {

    public void testParsing() throws Exception {
        PrintoutPullParser parser = new PrintoutPullParser();
        parser.parse(getInstrumentation().getContext().getResources().getXml(R.xml.printer_configuration));
    }
}
AgentKnopf
źródło
7
Tak, ale wydaje się głupie, że Android nie zapewnia dostępu do kontekstu projektu testowego w prostych testach JUnit. Kontekst znajduje się w AndroidTestCase.mTestContext, ale jest prywatny. Nie rozumiem dlaczego.
peceps
@peceps Full Ack - ale tak to już i mi się to nie podoba;)
AgentKnopf
25

Jak można przeczytać w kodzie źródłowym AndroidTestCase , getTestContext()metoda jest ukryta.

/**
 * @hide
 */
public Context getTestContext() {
    return mTestContext;
}

Możesz pominąć @hideadnotację za pomocą odbicia.

Po prostu dodaj następującą metodę w swoim AndroidTestCase:

/**
 * @return The {@link Context} of the test project.
 */
private Context getTestContext()
{
    try
    {
        Method getTestContext = ServiceTestCase.class.getMethod("getTestContext");
        return (Context) getTestContext.invoke(this);
    }
    catch (final Exception exception)
    {
        exception.printStackTrace();
        return null;
    }
}

Zadzwoń w getTestContext()dowolnym momencie. :)

Timothée Jeannin
źródło
2
Dla mnie zadziałało idealnie i ładuję zasoby za pomocą Context albo AndroidTestCase za pomocą tej metody, albo ActivityInstrumentationTestCase2.getInstrumentation () .getContext (), a następnie getResources () .getAssets ()
Andrew Mackenzie
Czy możesz spekulować, dlaczego ukryli to? Jeśli użyjemy tej techniki, czy mogliby usunąć tę metodę w późniejszym wydaniu (łamiąc nasz kod testowy)?
Andrew Shepherd
1
Dostajęjava.lang.NoSuchMethodException: android.test.ServiceTestCase.getTestContext()
kurdtpage
4

Aktualizacja: AndroidTestCase ta klasa została wycofana na poziomie API 24. Użyj InstrumentationRegistryzamiast tego. Nowe testy należy pisać przy użyciu biblioteki obsługi testów systemu Android. Link do ogłoszenia

Należy rozszerzyć z AndroidTestCase zamiast TestCase.

Omówienie klasy AndroidTestCase
Rozszerz to, jeśli potrzebujesz dostępu do zasobów lub innych rzeczy, które zależą od kontekstu działania.

AndroidTestCase - programiści Androida

eslamb
źródło
4

Jeśli chcesz uzyskać kontekst z Kotlinem i Mockito, możesz to zrobić w następujący sposób:

val context = mock(Context::class.java)

Mam nadzieję, że ci pomoże

Juanes30
źródło
uzyskiwanie wartości null w kontekście?
Deven
I nie zapomnij dodać adnotacji do klasy testowej za pomocą @RunWith (MockitoJUnitRunner :: class)
USMAN osman
2

To jest poprawny sposób na uzyskanie kontekstu. Inne metody są już przestarzałe

import androidx.test.platform.app.InstrumentationRegistry

InstrumentationRegistry.getInstrumentation().context
tomrozb
źródło
2
import androidx.test.core.app.ApplicationProvider;

    private Context context = ApplicationProvider.getApplicationContext();
eoinzy
źródło
1

Dla tych, którzy napotykają te problemy podczas tworzenia testów automatycznych, musisz zrobić to:

    Context instrumentationContext;

    @Before
    public void method() {

        instrumentationContext = InstrumentationRegistry.getInstrumentation().getContext();

        MultiDex.install(instrumentationContext);
    }
Sebastien FERRAND
źródło
0

Pozostałe odpowiedzi są nieaktualne. Obecnie za każdym razem, gdy rozszerzasz AndroidTestCase, istnieje obiekt mContext Context, którego możesz użyć.

Yoni Keren
źródło