Estoy tratando de escribir una prueba unitaria para algún código de Android que busque una clave específica presente en un objeto Intent . Como parte de mi prueba, estoy creando un objeto Intent y agregándole una Cadena. Sin embargo, cuando uso el siguiente código, mi variable se inicializa en nulo:
val data = Intent().putExtra("key", "value") // data is nullSi divido esto en dos líneas, funciona bien:
val data = Intent() data.putExtra("key", "value") // data is non-null and contains my key/value¿Qué característica del lenguaje Kotlin está causando que esto suceda?
Tenga en cuenta que putExtra() devuelve un objeto Intent . De la fuente de Android:
public @NonNull Intent putExtra(String name, String value) { if (mExtras == null) { mExtras = new Bundle(); } mExtras.putString(name, value); return this; } En el primer caso, el tipo inferido es Intent! . ¿Tenía la impresión de que esto solo significa que es una Intent o una Intent? pero Kotlin no quiere que los desarrolladores se vuelvan locos con los tipos de plataforma Java. Aún así, dado que putExtra() devuelve un valor no nulo, espero que el valor real de data no sea nulo.
La respuesta corta es lo que @CommonsWare y @TheWanderer mencionaron en los comentarios: mi clase de prueba estaba en el directorio test/ , por lo que estaba usando una implementación de Intent simulada en lugar de la real.
Cuando muevo mi prueba al directorio androidTest/ , todo funciona como se esperaba. El comportamiento observado no tiene nada que ver con Kotlin.
Alguna información adicional sobre por qué esto fue tan confuso...
Primero, me equivoqué cuando escribí esto:
val data = Intent() data.putExtra("key", "value") // data is non-null and contains my key/value
La variable data no era nula, pero en realidad no contenía mi par clave/valor. La implementación de la Intent simulada que estaba usando estaba descartando la llamada putExtra() .
Entonces, ¿por qué estaba pasando mi prueba?
La única prueba en particular en la que decidí profundizar fue probar el caso negativo (cuando una clave distinta a la que espera está presente en el Intent ). Pero no estaba pasando un Intent con la clave incorrecta, estaba pasando un Intent sin ninguna clave. Sin embargo, de cualquier manera, la clave esperada no está presente y el método devuelve false .
El caso positivo (donde la clave requerida en realidad se pasó a putExtra() ) falló con un AssertionError . Lástima que no elegí este para escudriñar.
Aparentemente, mi proyecto principal ha Intent.putExtra() como no operativo, a través de la returnDefaultValues = true gradle. Cuando creo un nuevo proyecto e intento reproducir este problema, aparece un error muy claro:
java.lang.RuntimeException: Method putExtra in android.content.Intent not mocked. See http://g.co/androidstudio/not-mocked for details. at android.content.Intent.putExtra(Intent.java) at com.example.stackoverflow.IntentTest.test(IntentTest.kt:12)
Desafortunadamente, con putExtra() , nunca recibí este mensaje útil.