Как мы можем получить доступ к контексту приложения в Robolectric?

112

На самом деле мне нужно получить ответ на вызов API, для этого мне нужно Context.

user1667968
источник

Ответы:

218

Обновить.

Просто используйте для версий 1.x и 2.x:

Robolectric.application;

А для версии 3.x:

RuntimeEnvironment.application;

А для версии 4.x:

  • добавьте в свой build.gradleфайл:

    testImplementation 'androidx.test:core:1.0.0'
    
  • получить контекст с помощью:

    ApplicationProvider.getApplicationContext()
    
Евгений Мартынов
источник
11
Вы ставили @RunWith (RobolectricTestRunner.class) для своих тестов?
Евгений Мартынов
4
Да .. Я добавил ... но все равно возвращается null
user1667968 04
1
Я сделал все, что вы упомянули, и все еще получаю null. Что еще мне может не хватать?
Мойзес Хименес
13
Также убедитесь, что вы не используете RuntimeEnvironment.applicationстатический код (например, методы, @BeforeClassпомеченные значком), поскольку Robolectric, вероятно, не будет инициализирован в этот момент, а значение будет null.
sfera 07
1
Также это вызывает кровотечение из приложения между тестами ... что может быть нежелательно,
Крис
26

Ты можешь использовать

RuntimeEnvironment.application
патроны
источник
4
в RoboElectric 3.0 приложение Roboelectric.application больше не существует, так что это, вероятно, лучший ответ
kenyee
19

Использовать это:

Robolectric.application
Xian
источник
16

Добавить

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

И используйте:

private val app = ApplicationProvider.getApplicationContext()
Джон
источник
import androidx.test.core.app.ApplicationProvider
luckyhandler
val appContext = ApplicationProvider.getApplicationContext <Context> ()
luckyhandler
2
Это правильный ответ с последней версией Robolectric. Другие упомянутые здесь методы устарели или удалены.
Габор
7

Для последней версии Robolectric 4.3 на данный момент в 2019 г.

ShadowApplication.getInstance ()

Roboletric.application

оба изношены. Итак, я использую

Context context = RuntimeEnvironment.systemContext;

чтобы получить Context.

The_Martian
источник
5

Чтобы получить контекст приложения, вы должны сделать следующее:

  1. аннотировать @RunWith (RobolectricTestRunner.class)
  2. RuntimeEnvironment.application.getApplicationContext ()
user1390616
источник
2

У меня это работает с Robolectric 3.5.1: ShadowApplication.getInstance().applicationContext

Фаррух Наджми
источник
Обратите внимание: похоже, что в версии 4.0 этот метод будет удален; лучше придерживаться RuntimeEnvironment.applicationили RuntimeEnvironment.application.getApplicationContext()если он работает для вас.
qix
2

В выпуске 4.0-alpha-3 от 21 июля они удалены ShadowApplication.getApplicationContext() . Используйте RuntimeEnvironment.application.getApplicationContext()для любых тестов, помеченных @RunWith(RobolectricTestRunner::class).

Кроме того, в их текущем руководстве есть пример получения строковых ресурсов с использованием:

final Context context = RuntimeEnvironment.application;

(Обратите внимание, что документация javadocs для RuntimeEnvironmentи в ShadowApplicationнастоящее время отражает не-альфа-версию 3.x.)

qix
источник
2

Сначала добавьте в свой build.gradle:

testImplementation 'androidx.test:core:1.2.0'

затем используйте:

ApplicationProvider.getApplicationContext() as Application

Дуги
источник
2

В некоторых случаях вам может потребоваться контекст вашего приложения вместо контекста по умолчанию Robolectris. Например, если вы хотите получить имя вашего пакета. По умолчанию Robolectric вернет вам org.robolectric.defaultназвание пакета. Чтобы получить настоящее имя пакета, сделайте следующее:

build.gradle

testImplementation 'org.robolectric:robolectric:4.2.1'

Ваш тестовый класс:

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

}

Убедитесь, что в вашем рабочем каталоге Run / Debug Configurations установлено значение: $ MODULE_DIR $ введите описание изображения здесь введите описание изображения здесь

Кирилл Кармазин
источник
1

Безопаснее использовать Robolectric.getShadowApplication()вместо Robolectric.applicationпрямого использования .

drspaceboo
источник
Но что, если мне нужно получить доступ к некоторым настраиваемым свойствам моего настраиваемого приложения? Кажется, я не могу получить реальный объект из теневого приложения.
Денис Княжев
@DenisKniazhev Извините, я не могу вам ответить. Вскоре после того, как мы начали использовать Robolectric, мы начали использовать Travis в качестве нашего CI, и они не очень хорошо работают. Я предполагаю, что вы можете либо применить его к своему приложению, либо вам может потребоваться создать собственный бегун, чтобы получить к нему доступ таким образом.
Желаем
Спасибо, а пока я просто придерживалсяRobolectric.application
Денис Княжев
6
Robolectric.getShadowApplication () недоступен
Игорь Ганапольский 01
1

Согласен с ответами @EugenMartynov и @rds ....

Быстрый пример можно найти на Volley-Marshmallow-Release

в NetworkImageViewTest.java

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

Ссылка Volley доступна https://android.googlesource.com/platform/frameworks/volley/+/marshmallow-release

вам нужно добавить зависимости в модуле волейбола в студии Android как:

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

Bhuro
источник
1

В вашем случае, я думаю, вам следует помнить о том, что вы на самом деле тестируете. Иногда возникновение проблем с непроверяемым кодом или кажущимся непроверяемым кодом является признаком того, что, возможно, ваш код нуждается в рефакторинге.

Для ответа на вызов API вы можете не захотеть тестировать сам вызов API. Возможно, нет необходимости проверять возможность отправки / получения информации от любой произвольной веб-службы, а скорее то, что ваш код обрабатывает и обрабатывает ваш ответ ожидаемым образом.

В этом случае может быть лучше провести рефакторинг кода, который вы пытаетесь протестировать. Разделите синтаксический анализ / обработку ответов на другой класс, который принимает простой, Stringи проведите тестирование этого класса , введя образцы строковых ответов.

Это более или менее соответствует идеям единой ответственности и инверсии зависимостей ( S и D в SOLID )

Grego
источник
1

Хорошо, поэтому я знаю, что многие другие говорили этот ответ раньше и, возможно, уже устарели

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

Я получил null, потому что часть when () была ПОСЛЕ инициализации sut. Это может помочь некоторым из вас.

также у меня есть

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

в начале урока

Также

 when(mockApplication.getApplicationContext()).thenReturn(RuntimeEnvironment.application.getApplicationContext()); works
Кара
источник