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)
// ...
}
Si cualquiera de nuestros anwers como una solución a su problema, por favor, marcarlos como una respuesta aceptada :) – Xilconic