Так как этот вопрос и ответы помогли мне несколько лет спустя, я подумал, что добавлю свое собственное предложение, которое будет заключаться в assert
, что dataPosition()
в конце чтения был таким же, как в конец записи. Опираясь на ответ Xilconic :
@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, немного лямбда и магии reifying:
class ParcelWrap(val value: T)
val T.parcel: ParcelWrap get() = ParcelWrap(this)
inline fun ParcelWrap.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(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
избегает необходимости переопределять параметр универсального типа, используя этот ответ .
Или, для более сложных утверждений:
testObject.parcel.test {
assertEquals(123, it.id)
assertEquals("dewey", it.name)
// ...
}
Я попробовал его несколько раз для предотвращения кэша файла и нашел голову +, хвост был быстр, но рубин был самым быстрым:
$ wc -l myfile.txt
920391 myfile.txt
$ time awk NR==334227 myfile.txt
my_searched_line
real 0m14.963s
user 0m1.235s
sys 0m0.126s
$ time head -334227 myfile.txt |tail -1
my_searched_line
real 0m5.524s
user 0m0.569s
sys 0m0.725s
$ time sed '334227!d' myfile
my_searched_line
real 0m12.565s
user 0m0.814s
sys 0m0.398s
$ time ruby -ne '$.==334227 and (print; exit)' myfile
my_searched_line
real 0m0.750s
user 0m0.568s
sys 0m0.179s