Получить контекст тестового проекта в тестовом примере Android junit

108

Кто-нибудь знает, как получить контекст проекта Test в тестовом примере Android junit (расширяет AndroidTestCase).

Примечание. Тест НЕ ЯВЛЯЕТСЯ инструментальным.

Примечание 2. Мне нужен контекст тестового проекта, а не контекст реального тестируемого приложения.

Мне это нужно, чтобы загрузить некоторые файлы из ресурсов из тестового проекта.

Peceps
источник
Почему нельзя просто использовать InstrumentationTestCase?
Yorkw
1
Потому что я тестирую сервисы, а не UI.
peceps
1
Здесь найден лучший ответ: [Использование AndroidTestCase вместо теста JUnit] [1] [1]: stackoverflow.com/questions/3170706/…
Хайме Ботеро

Ответы:

137

Есть новый подход с библиотекой поддержки тестирования Android (в настоящее время androidx.test:runner:1.1.1). Обновленный пример Котлина:

class ExampleInstrumentedTest {

    lateinit var instrumentationContext: Context

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

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

Если вы хотите также запустить контекст приложения:

InstrumentationRegistry.getInstrumentation().targetContext

Полный рабочий пример: https://github.com/fada21/AndroidTestContextExample

Посмотрите здесь: в чем разница между getTargetContext () и getContext (в InstrumentationRegistry)?

fada21
источник
1
Наконец, ответ о том, как использовать JUnit4 с InstrumentationTest. После нескольких часов поисков. Должен любить разработку под Android.
Fabian Zeindl
1
Ницца! tx (обратите внимание, что у вашего ученика есть опечатка)
Грег
1
Может ли кто-нибудь помочь о том, какие зависимости необходимо добавить в файл gradle, чтобы это работало?
Грег
1
Не забудьте добавить compile "com.android.support.test:runner:1.0.1"в свой градл
егорикем
2
Он устарел, используйте InstrumentationRegistry.getInstrumentation().contextвместо него.
Allan Veloso
37

После некоторых исследований кажется, что единственное рабочее решение - это то, на которое уже указывал Йорк. Вам нужно будет расширить InstrumentationTestCase, а затем вы сможете получить доступ к контексту вашего тестового приложения с помощью getInstrumentation (). GetContext () - вот краткий фрагмент кода с использованием приведенных выше предложений:

public class PrintoutPullParserTest extends InstrumentationTestCase {

    public void testParsing() throws Exception {
        PrintoutPullParser parser = new PrintoutPullParser();
        parser.parse(getInstrumentation().getContext().getResources().getXml(R.xml.printer_configuration));
    }
}
АгентКнопф
источник
7
Да, но кажется глупым, что Android не предоставляет доступ к контексту тестового проекта в простых тестах JUnit. Контекст есть в AndroidTestCase.mTestContext, но он частный. Не понимаю почему.
peceps
@peceps Full Ack - но так оно и есть, и мне это тоже не нравится;)
AgentKnopf
25

Как вы можете прочитать в исходном коде AndroidTestCase , getTestContext()метод скрыт.

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

Вы можете обойти @hideаннотацию, используя отражение.

Просто добавьте следующий метод в свой 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;
    }
}

Тогда звоните в getTestContext()любое время, когда захотите. :)

Тимоти Жаннин
источник
2
У меня отлично сработало, и я загружаю ресурсы с помощью Context либо из AndroidTestCase с помощью этого метода, либо с помощью ActivityInstrumentationTestCase2.getInstrumentation () .getContext (), затем getResources () .getAssets ()
Эндрю Маккензи
Можете ли вы предположить, почему они скрыли это? Если мы воспользуемся этой техникой, могут ли они убрать этот метод в более позднем выпуске (нарушив наш тестовый код)?
Эндрю Шеперд
1
Я получаюjava.lang.NoSuchMethodException: android.test.ServiceTestCase.getTestContext()
kurdtpage
4

Обновление: AndroidTestCase этот класс устарел на уровне API 24. Используйте InstrumentationRegistryвместо него. Новые тесты следует писать с использованием библиотеки поддержки тестирования Android. Ссылка на объявление

Вы должны расширять AndroidTestCase вместо TestCase.

Обзор класса AndroidTestCase
Расширьте это, если вам нужен доступ к ресурсам или другим вещам, которые зависят от контекста активности.

AndroidTestCase - Разработчики Android

eslamb
источник
4

Если вы хотите получить контекст с помощью Kotlin и Mockito, вы можете сделать это следующим образом:

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

Надеюсь, это поможет тебе

Хуанес30
источник
получить нуль в контексте?
Девен
И не забудьте аннотировать свой тестовый класс с помощью @RunWith (MockitoJUnitRunner :: class)
USMAN osman
2

Это правильный способ получения контекста. Другие методы уже устарели

import androidx.test.platform.app.InstrumentationRegistry

InstrumentationRegistry.getInstrumentation().context
томрозб
источник
2
import androidx.test.core.app.ApplicationProvider;

    private Context context = ApplicationProvider.getApplicationContext();
эоинзи
источник
1

Тем, кто сталкивается с этими проблемами при создании автоматических тестов, необходимо сделать следующее:

    Context instrumentationContext;

    @Before
    public void method() {

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

        MultiDex.install(instrumentationContext);
    }
Себастьян ФЕРРАН
источник
0

Остальные ответы устарели. Прямо сейчас каждый раз, когда вы расширяете AndroidTestCase, существует объект mContext Context, который вы можете использовать.

Йони Керен
источник