由于这个问题和答案在几年后帮助了我,我想我会添加我自己的建议,即 assert 阅读末尾的 dataPosition() 与写结束。建立在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());
}
背景:这是在我花了(令人尴尬的)时间调试一个糟糕的Parcelable 之后才想到的。在我的例子中,writeToParcel 正在从一个中等复杂的对象图中的一个对象写入一个重复字段。因此,后续对象被错误读取,产生误导性异常,并且在使用特定异常对象的测试中没有错误。
追踪起来很痛苦,然后我意识到检查 dataPosition 会更快地查明问题,因为我对内部对象和主容器进行了测试。
Kotlin:因为我在 Kotlin 工作,所以有点 lambda 和具体化魔法:
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
}
如果有完整可靠的equals(),我现在可以很容易地按照这些思路进行测试:
testObject.parcel.test { assertEquals(testObject, it) }
注意.parcel.test 避免了使用this answer 重新指定泛型类型参数。
或者,对于更复杂的断言:
testObject.parcel.test {
assertEquals(123, it.id)
assertEquals("dewey", it.name)
// ...
}