-
-
Save tomaszpolanski/92a2eada1e06e4a4c71abb298d397173 to your computer and use it in GitHub Desktop.
import android.annotation.SuppressLint | |
import android.os.Parcelable | |
import kotlinx.android.parcel.Parcelize | |
@SuppressLint("ParcelCreator") // IntelliJ Issue https://youtrack.jetbrains.com/issue/KT-19300 | |
@Parcelize | |
data class Movie(val title: String) : Parcelable |
import android.os.Parcel | |
import android.support.test.runner.AndroidJUnit4 | |
import org.assertj.core.api.Assertions.assertThat | |
import org.junit.Test | |
import org.junit.runner.RunWith | |
@RunWith(AndroidJUnit4::class) | |
class MovieTest { | |
@Test | |
fun verify_parceling() { | |
val movie = Movie("Infinity War") | |
movie.testParcel() | |
.apply { | |
assertThat(this).isEqualTo(movie) | |
assertThat(this).isNotSameAs(movie) | |
} | |
} | |
} |
import android.os.Bundle | |
import android.os.Parcel | |
import android.os.Parcelable | |
inline fun <reified R : Parcelable> R.testParcel(): R { | |
val bytes = marshallParcelable(this) | |
return unmarshallParcelable(bytes) | |
} | |
inline fun <reified R : Parcelable> marshallParcelable(parcelable: R): ByteArray { | |
val bundle = Bundle().apply { putParcelable(R::class.java.name, parcelable) } | |
return marshall(bundle) | |
} | |
fun marshall(bundle: Bundle): ByteArray = | |
Parcel.obtain().use { | |
it.writeBundle(bundle) | |
it.marshall() | |
} | |
inline fun <reified R : Parcelable> unmarshallParcelable(bytes: ByteArray): R = unmarshall(bytes) | |
.readBundle() | |
.run { | |
classLoader = R::class.java.classLoader | |
getParcelable(R::class.java.name) | |
} | |
fun unmarshall(bytes: ByteArray): Parcel = | |
Parcel.obtain().apply { | |
unmarshall(bytes, 0, bytes.size) | |
setDataPosition(0) | |
} | |
private fun <T> Parcel.use(block: (Parcel) -> T): T = | |
try { | |
block(this) | |
} finally { | |
this.recycle() | |
} |
Nothing?
is a strange type to have. This type should not be serializable. Do you have in your parcel Nothing?
type?
No I don't.
It happens in Android Studio when I copy/paste utils.kt in the test
folder.
Does it only work in the androidTest
folder, then?
It should work everywhere. The last time I've used the code was 2 years ago and kotlin changes most likely has changed it.
Could you include the whole stacktrace?
Again, that's all I have, no stack trace, it appears on Android Studio right after a copy/paste of that class.
Last thing, what kotlin version are you using?
1.6.21
The last last thing, is there a reason why you are not using https://developer.android.com/kotlin/parcelize ?
This solution was used before parcelize
I use parcelize, but I wanted to unit test a quite tricky use case, where one of the attribute of my parcelable object is of type Any
, so I have to to the write(parcel: Parcel, flags: Int)
and the create(parcel: Parcel)
by myself.
Those two approaches do the same thing in a different way, therefore UT your prod code using this approach would actually not test the same functionality.
Did you consider using epresso tests for your current implementation?
I can only use pure unit test, since I'm working on a Flutter project (so there is no integration testing available, therefore I can't use Espresso).
But that's ok, I'll find another way, thanks.
I also work with flutter and you can write Espresso tests there. You can check out this link
Oh cool, I didn't know, thanks for the link!
The issue comes from getParcelable
now correctly being annotated with @Nullable
.
You can update the unmarshallParcelable
return type to R?
to fix this issue.
I have a probe with
unmarshallParcelable()
, I get the following error:How can I fix that?
Thanks.