2012-10-10 37 views
28

¿Cómo se prueba la unidad Parcelable? He creado una clase parcelable, y escribí esta prueba unitariaAndroid Unit Testing: Paquete/Parcelable

TestClass test = new TestClass(); 
Bundle bundle = new Bundle(); 
bundle.putParcelable("test", test); 

TestClass testAfter = bundle.getParcelable("test"); 
assertEquals(testAfter.getStuff(), event1.getStuff()); 

deliberadamente tratar de fallar la prueba mediante la devolución nula en el createFromParcel(), pero parece tener éxito. Parece que no se empaqueta hasta que se necesite. ¿Cómo fuerzo el paquete a ... paquete?

+1

Si cualquiera de nuestros anwers como una solución a su problema, por favor, marcarlos como una respuesta aceptada :) – Xilconic

Respuesta

81

He encontrado este enlace que muestra cómo se puede probar la unidad un objeto parcelable: http://stuffikeepforgettinghowtodo.blogspot.nl/2009/02/unit-test-your-custom-parcelable.html

En realidad se puede saltar el Bundle si don 'Realmente necesita incluirlo como Zorch hizo su sugerencia. A continuación, obtener algo como esto:

public void testTestClassParcelable(){ 
    TestClass test = new TestClass(); 

    // Obtain a Parcel object and write the parcelable object to it: 
    Parcel parcel = Parcel.obtain(); 
    test.writeToParcel(parcel, 0); 

    // After you're done with writing, you need to reset the parcel for reading: 
    parcel.setDataPosition(0); 

    // Reconstruct object from parcel and asserts: 
    TestClass createdFromParcel = TestClass.CREATOR.createFromParcel(parcel); 
    assertEquals(test, createdFromParcel); 
} 
+3

'parcel.setDataPosition (0);' era el secreto. Gracias – scorpiodawg

+0

Funciona para mí también. ¡Gracias!. – ernestkamara

+0

¡No tiene ninguna posibilidad de trabajar! Siempre obtendrás '' 'BadParcelableException'''. – ddmytrenko

16

Puede hacerlo de esta manera:

//Create parcelable object and put to Bundle 
    Question q = new Question(questionId, surveyServerId, title, type, answers); 
    Bundle b = new Bundle(); 
    b.putParcelable("someTag", q); 

//Save bundle to parcel 
    Parcel parcel = Parcel.obtain(); 
    b.writeToParcel(parcel, 0); 

//Extract bundle from parcel 
    parcel.setDataPosition(0); 
    Bundle b2 = parcel.readBundle(); 
    b2.setClassLoader(Question.class.getClassLoader()); 
    Question q2 = b2.getParcelable("someTag"); 

//Check that objects are not same and test that objects are equal 
    assertFalse("Bundle is the same", b2 == b); 
    assertFalse("Question is the same", q2 == q); 
    assertTrue("Questions aren't equal", q2.equals(q)); 
+0

Ha intentado con este tipo de afirmación: 'Assert .assertTrue (EqualsBuilder.reflectionEquals (q2, q)); '? Lo pregunto porque en caso de que tenga una 'Lista = new ArrayList ' como un campo en su modelo de datos 'Question.java', entonces el código que usted escribió no funciona.Si tiene 'ArrayList = new ArrayList ' funciona. ¿Sabes cómo arreglar ésto? –

1

Desde esta pregunta y las respuestas me ayudaron varios años en la línea, pensé que me gustaría añadir mi propia sugerencia, lo que sería a assert que el dataPosition() al final de la lectura fue la misma que al final de la escritura. Sobre la base de Xilconic's answer:

@Test 
public void testTestClassParcelable(){ 
    TestClass test = new TestClass(); 

    // Obtain a Parcel object and write the parcelable object to it: 
    Parcel parcel = Parcel.obtain(); 
    test.writeToParcel(parcel, 0); 

    //>>>>> Record dataPosition 
    int eop = parcel.dataPosition(); 

    // After you're done with writing, you need to reset the parcel for reading: 
    parcel.setDataPosition(0); 

    // Reconstruct object from parcel and asserts: 
    TestClass createdFromParcel = TestClass.CREATOR.createFromParcel(parcel); 
    assertEquals(test, createdFromParcel); 

    //>>>>> Verify dataPosition 
    assertEquals(eop, parcel.dataPosition()); 
} 

Antecedentes: Esto vino a mí después de pasar una cantidad (vergonzoso) de tiempo de depuración una mala Parcelable. En mi caso, writeToParcel estaba escribiendo un campo duplicado de un objeto dentro de un gráfico de objetos moderadamente complejo. Por lo tanto, objetos posteriores se leyeron incorrectamente, dando excepciones engañosas y sin errores en las pruebas con el objeto que se porta mal.

Fue un dolor de encontrar, y luego me di cuenta de que al comprobar dataPosition habría identificado el problema más rápido ya que tengo pruebas en objetos internos, así como en el contenedor principal.


Kotlin: Desde que estoy trabajando en el Kotlin, un poco lambda y reificante mágica:

class ParcelWrap<T>(val value: T) 

val <T> T.parcel: ParcelWrap<T> get() = ParcelWrap(this) 

inline fun <reified T: Parcelable> ParcelWrap<T>.test(
     flags: Int = 0, 
     classLoader: ClassLoader = T::class.java.classLoader, 
     checks: (T) -> Unit 
): T { 
    // Create the parcel 
    val parcel: Parcel = Parcel.obtain() 
    parcel.writeParcelable(this.value, flags) 

    // Record dataPosition 
    val eop = parcel.dataPosition() 

    // Reset the parcel 
    parcel.setDataPosition(0) 

    // Read from the parcel 
    val newObject = parcel.readParcelable<T>(classLoader) 

    // Perform the checks provided in the lambda 
    checks(newObject) 

    // Verify dataPosition 
    assertEquals("writeToParcel wrote too much data or read didn't finish reading", eop, parcel.dataPosition()) 
    return newObject 
} 

ahora puedo probar muy fácilmente a lo largo de estas líneas, si hay una completa y fiable equals() :

testObject.parcel.test { assertEquals(testObject, it) } 

Nota del .parcel.test evita tener que volver a especificar parámetro de tipo genérico utilizando this answer.

O, por afirmaciones más complejas:

testObject.parcel.test { 
    assertEquals(123, it.id) 
    assertEquals("dewey", it.name) 
    // ... 
}