Hello everybody, not sure if that may be a MockK i...
# compose-android
d
Hello everybody, not sure if that may be a MockK issue, but let’s start posting here and let’s see 🙂 I have a mapper that maps from
LazyPagingItems
to my model/state (I do that in the presenter, using Molecule, if you’re wondering) In order to test that, I created this convenience mock (since
LPI
has internal constructor)
Copy code
fun <T : Any> mockLazyPagingItems(isEmpty: Boolean, refresh: LoadState): LazyPagingItems<T> = mockk {
    every { loadState } returns mockk loadState@{
        every { this@loadState.refresh } returns refresh
        every { this@loadState.append } returns LoadState.Loading
        every { this@loadState.prepend } returns LoadState.Loading
    }
    every { itemCount } returns if (isEmpty) 0 else 1
}
Updating to alpha19 I now have this exception (full stacktrace in thread)
java.lang.NullPointerException: Cannot invoke “androidx.compose.runtime.State.getValue()” because “$this$getValue$iv” is null
How would I fix that?
full stack trace
s
It seems like LazyPagingItems are reading some state that wasn't initialized because of mockk
d
I would get a mock exception "no answer found blabla" 🤔 My guess is that that
$iv
is something from the IR, no? 🤔
I didn't have time to dive yet. By the way I think it would be nice having a test artifact that provides a way to create an instance of a
LPI
, but I'm not sure in which scenarios that would be useful besides mine, as it would be impossible to get a
LPI
outside of the UI without Molecule (as
collectAsLazyPagingItems
is the only way)
I dig a bit more, and I assume the problem is that
loadState
is now a delegate. I instantiated a
LPI
using reflection, but I’ve not been able to run my tests correctly, as I’ve not been able to update the snapshot list under test 😞
I think I’ll create a surrogate of
LPI
and create a surrogate mapper in between, so I can test my mapper (
m2
) using the surrogate
Copy code
LazyPagingItems (m1)-> LazyPagingItemsSurrogate (m2)-> PagingItemsState
i
I have a mapper that maps from LazyPagingItems to my model/state (I do that in the presenter, using Molecule, if you're wondering)
This is the wrong thing to do in the first place. Map your Flow<PagingData> using the operators provided by Paging at that level
d
I'm not trying to map the models, I want a declarative state for the UI, which can be: • Empty • Items (also loading or not) • Loading • Error (also loading or not) While LPI provides a set of about 50 combinations or more 😁
i
I'm a bit confused, since Loading is completely covered by Empty and Items? The number of items and load state are independent properties
Sounds like you just need a Kotlin extension that takes CombinedLoadState and make it into the simplified view of the world you want?
E.g., Loading, Loaded, or Error?
d
Yes, they're independent, but in my UI logic one depends on the other (eg, when loading I'd show something different regarding whether I have items or not). That was my purpose, but encapsulated in a (generic) mapper class with tests 😊
i
And I'm still not entirely sure where mocking this comes into the picture? You can create a fake Flow<PagingData> easily enough and just use the actual collectAsLazyPagingItems()?
d
I did solve with the surrogate tho, a bit verbose, but it does its job
Using the collectAsLazyPagingItems didn't work as expected under JUnit test, at least with my setup
i
E.g.,
flowOf(PagingData.from(...)).collectAsLazyPagingItems()
d
The snapshot list was never updated in my case. I also tried using Dispatchers.setMain, but didn't help
i
Seems like you should have led with "how do I get collectAsLazyPagingItems working in my test" rather than bringing up a problem a few steps down the wrong path - that way we'd avoid that XY Problem: https://en.wikipedia.org/wiki/XY_problem
d
True 😁 the reason is because the test was working as expected, but the update to alpha19 changed that, so the history conditioned my question
But I was also thinking now that using collectAsLPI would led to another problem: I'd need to test using the Flow coming from the library, which emission is subject to changes: e.g. the first emitted LPI has changed in some way on alpha17
i
You'll really probably want to wait one more build, since it only then that PagingData.from instantly provide the static state to the first composition if you use it with StateFlow (e.g.
MutableStateFlow(PagingData.from...))
)
Since that'll be the build that this change is released in
d
Thank you for the info, I'm also super excited about the previews 🥳
346 Views