¿Cómo podemos acceder al contexto de una aplicación en Robolectric?

112

En realidad, necesito obtener una respuesta de una llamada a la API, para eso lo solicité Context.

usuario1667968
fuente

Respuestas:

218

Actualizar.

Solo use para la versión 1.xy 2.x:

Robolectric.application;

Y para la versión 3.x:

RuntimeEnvironment.application;

Y para la versión 4.x:

  • agregar a su build.gradlearchivo:

    testImplementation 'androidx.test:core:1.0.0'
    
  • recuperar el contexto con:

    ApplicationProvider.getApplicationContext()
    
Eugen Martynov
fuente
11
¿Pusiste @RunWith (RobolectricTestRunner.class) para tus pruebas?
Eugen Martynov
4
Sí ... agregué ... pero aún así devuelve nulo
user1667968
1
He hecho todo lo que mencionaste y aún obtengo nulo. ¿Algo más que pueda estar perdiendo?
Moises Jimenez
13
También asegúrese de no usar RuntimeEnvironment.applicationen código estático (como los métodos anotados con @BeforeClass) ya que Robolectric probablemente no se inicializará en ese punto y el valor será null.
sfera
1
Además, esto hace que la aplicación sangra entre las pruebas ... lo que puede no ser deseable
Chris
26

Puedes usar

RuntimeEnvironment.application
rds
fuente
4
en RoboElectric 3.0, Roboelectric.application ya no existe, por lo que esta es probablemente la mejor respuesta
kenyee
19

Utilizar este:

Robolectric.application
Xian
fuente
16

Añadir

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

Y use:

private val app = ApplicationProvider.getApplicationContext()
Juan
fuente
importar androidx.test.core.app.ApplicationProvider
luckyhandler
val appContext = ApplicationProvider.getApplicationContext <Context> ()
luckyhandler
2
Esta es la respuesta correcta con el último Robolectric. Otros métodos mencionados aquí están obsoletos o eliminados.
Gabor
7

Para el último Robolectric 4.3 a partir de ahora en 2019 '

ShadowApplication.getInstance ()

y

Aplicación Roboletric.

Ambos están depricados. Entonces estoy usando

Context context = RuntimeEnvironment.systemContext;

para obtener el contexto.

El marciano
fuente
5

Para obtener el contexto de la aplicación, debe hacer lo siguiente:

  1. anotar @RunWith (RobolectricTestRunner.class)
  2. RuntimeEnvironment.application.getApplicationContext ()
usuario1390616
fuente
2

Esto me funciona con Robolectric 3.5.1: ShadowApplication.getInstance().applicationContext

Farrukh Najmi
fuente
Tenga en cuenta que parece que la versión 4.0 eliminará este método; es mejor quedarse con RuntimeEnvironment.applicationo RuntimeEnvironment.application.getApplicationContext()si funciona para usted.
qix
2

A partir del lanzamiento 4.0-alpha-3 del 21 de julio, eliminaron ShadowApplication.getApplicationContext() . Siga RuntimeEnvironment.application.getApplicationContext()para cualquier prueba anotada con @RunWith(RobolectricTestRunner::class).

Como acotación al margen, su guía actual tiene un ejemplo de cómo obtener recursos de cadena usando:

final Context context = RuntimeEnvironment.application;

(Tenga en cuenta que los javadocs para RuntimeEnvironmenty ShadowApplicationactualmente reflejan la versión 3.x no alfa).

qix
fuente
2

Primero agregue lo siguiente a su build.gradle:

testImplementation 'androidx.test:core:1.2.0'

luego usa:

ApplicationProvider.getApplicationContext() as Application

dougie
fuente
2

En algunos casos, es posible que necesite el contexto de su aplicación en lugar del contexto predeterminado de Robolectris. Por ejemplo, si desea obtener el nombre de su paquete. Por defecto, Robolectric le devolverá el org.robolectric.defaultnombre del paquete. Para obtener el nombre real de su paquete, haga lo siguiente:

build.gradle

testImplementation 'org.robolectric:robolectric:4.2.1'

Tu clase de prueba:

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

}

Asegúrese de que en su directorio de trabajo Run / Debug Configurations esté establecido en: $ MODULE_DIR $ ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

Kirill Karmazin
fuente
1

Es más seguro usarlo en Robolectric.getShadowApplication()lugar de usarlo Robolectric.applicationdirectamente.

drspaceboo
fuente
Pero, ¿qué sucede si necesito acceder a algunas propiedades personalizadas de mi aplicación personalizada? Parece que no puedo obtener el objeto real de la aplicación de sombra.
Denis Kniazhev
@DenisKniazhev Lo siento, no puedo responder eso por ti. Poco después de que comenzamos a usar Robolectric, comenzamos a usar Travis como nuestro CI, y no funcionan bien. Supongo que puede enviarlo a su aplicación o es posible que necesite crear un corredor personalizado para acceder a él de esa manera. La mejor de las suertes
drspaceboo
Gracias, por ahora acabo de Robolectric.application
seguir
6
Robolectric.getShadowApplication () no está disponible
IgorGanapolsky
1

De acuerdo con las respuestas de @EugenMartynov y @rds ....

Se puede encontrar un ejemplo rápido en Volley-Marshmallow-Release

en NetworkImageViewTest.java

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

El enlace de Volley está disponible https://android.googlesource.com/platform/frameworks/volley/+/marshmallow-release

tienes que agregar dependencias en el módulo de volley en Android Studio como:

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

Bhuro
fuente
1

En su caso, creo que debería tener en cuenta lo que está probando. A veces, encontrarse con problemas de código no comprobable o código aparentemente no comprobable es una señal de que tal vez su código deba ser refactorizado.

Para una respuesta a una llamada de API, es posible que no desee probar la propia llamada de API. Puede que no sea necesario probar que es posible enviar / recibir información de cualquier servicio web arbitrario, sino que su código maneja y procesa su respuesta de la manera esperada.

En cuyo caso, sería mejor refactorizar el código que está intentando probar. Divida el análisis / manejo de respuestas en otra clase que acepte un simple Stringy haga sus pruebas en esa clase inyectando respuestas de cadena de muestra.

Esto es más o menos siguiendo las ideas de Responsabilidad Única e Inversión de Dependencia (La S y D en SOLID )

grego
fuente
1

Ok, sé que muchos otros dijeron esta respuesta antes y es posible que ya estén desactualizados

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

Obtuve nulo, porque la parte when () fue DESPUÉS de la inicialización de sut. Podría ayudar a algunos de ustedes.

tambien tengo el

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

al comienzo de la clase

también

 when(mockApplication.getApplicationContext()).thenReturn(RuntimeEnvironment.application.getApplicationContext()); works
Karoly
fuente