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


112

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

Ответы:


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


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.


5

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

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

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


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прямого использования .


Но что, если мне нужно получить доступ к некоторым настраиваемым свойствам моего настраиваемого приложения? Кажется, я не могу получить реальный объект из теневого приложения.
Денис Княжев

@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' }


1

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

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

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

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


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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.