Какая разница между getTargetContext() и getContext (на InstrumentationRegistry)?

Я использую новую библиотеку поддержки тестирования Android (com.android.support.test:runner:0.2) для запуска контрольных тестов (a.k.a Тесты устройств или эмуляторов).

Я комментирую свой тестовый класс с помощью @RunWith(AndroidJUnit4.class) и использую Android Studio для их запуска.

Для моих тестовых случаев мне нужен экземпляр Context. Я могу получить его с помощью InstrumentationRegistry, но он имеет два связанных с контекстом методов, и неясно, в чем разница.

В чем разница между InstrumentationRegistry.getContext() и InstrumentationRegistry.getTargetContext()?

Ответ 1

InstrumentationRegistry - это открытый экземпляр реестра, который содержит ссылку на инструментарий, запущенный в процессе, и аргументирует его, а также позволяет внедрять следующие экземпляры:

  • InstrumentationRegistry.getInstrumentation(), возвращает инструмент, работающий в данный момент.
  • InstrumentationRegistry.getContext(), возвращает контекст этого пакета инструментария.
  • InstrumentationRegistry.getTargetContext(), возвращает контекст приложения целевого приложения.
  • InstrumentationRegistry.getArguments(), возвращает копию аргумента Bundle, который был передан в эту Инструментацию. Это полезно, когда вы хотите получить доступ к аргументам командной строки, переданным в Instrumentation для вашего теста.

РЕДАКТИРОВАТЬ:

Так, когда использовать getContext() против getTargetContext()?

Документация не делает большую работу по объяснению различий, так что вот от моего POV:

Вы знаете, что когда вы проводите тестирование на Android, у вас есть два приложения:

  1. Тестовое приложение, которое выполняет вашу тестовую логику и тестирует ваше "настоящее" приложение
  2. "Настоящее" приложение (которое увидят ваши пользователи)

Поэтому, когда вы пишете свои тесты и хотите загрузить ресурс вашего реального приложения, используйте getTargetContext().

Если вы хотите использовать ресурс вашего тестового приложения (например, тестовый ввод для одного из ваших тестов), тогда вызовите getContext().

Ответ 2

Вам может понадобиться InstrumentationRegistry.getContext() для доступа к исходным ресурсам тестового примера.

Например, для доступа к app/src/androidTest/res/raw/resource_name.json в TestCase:

final Context context = InstrumentationRegistry.getContext(); InputStream is = context.getResources().openRawResource(com.example.package.test.R.raw.resource_name);

Ответ 3

Мне потребовались часы, чтобы выяснить это.

У случая InstrumentedTest был элемент контекста, который был установлен в настройке следующим образом:

context = InstrumentationRegistry.getTargetContext();

это использовалось для открытия файлов, особенно таких вещей:

String filenameOriginal = context.getCacheDir() + "/initial.csv";

Теперь я решил, что мне нужно использовать какой-то ресурс, который доступен только в инструментальном тесте, я не хотел распространять этот ресурс вместе с версией выпуска. Поэтому я воссоздал тестируемые каталоги ресурсов:

app\src\androidTest
└───res
    └───raw
            v1.csv

Но чтобы использовать это в коде, я должен был вызвать что-то вроде этого:

    public static Uri resourceToUri(Context context, int resID)
    {
        return Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
                context.getResources().getResourcePackageName(resID) + '/' +
                context.getResources().getResourceTypeName(resID) + '/' +
                context.getResources().getResourceEntryName(resID));
    }

    resourceToUri(context, R.raw.v1)

Что всегда было бы неудачно, потому что R.raw.v1 совпадал с чем-то, что было на самом деле в моем файле ресурсов R из основного приложения. При использовании ресурсов в инструментальных тестах было создано два R файла. Чтобы исправить это, я должен был включить тестовый файл R:

import com.my_thing.app.my_app.test.R;

однако вызов resourceToUri таком случае завершится неудачно.

Проблема заключалась в том, что я должен был использовать не InstrumentationRegistry.getTargetContext() а скорее InstrumentationRegistry.getInstrumentation().getContext() чтобы получить ресурс R.raw.v1 поэтому я слепо заменяю настройку контекста для всего тестового класса. в

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

Это работало хорошо для конкретного теста, но другие тесты в тестовом примере начали терпеть неудачу с отказом в разрешении для имени filenameOriginal я использовал выше.

Оказалось, что, заменив контекст на контекст инструментария, я получил путь, к которому мое приложение не имело доступа, и я получил FileNotFoundException с permission denied и GrantTestRule или другие вещи не будут работать.

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