Closed eboudrant closed 8 months ago
Ok, my understanding is you can pass the view model to the composable and build a view model / state for the preview composable.
@Preview
@Composable
fun MyComposablePreview() {
Mavericks.initialize(debugMode = true)
MyComposable(
MyViewModel(MyState())
)
}
@Composable
fun MyComposable(viewModel: MyViewModel ) {
....
}
Is it the recommended way?
Passing the ViewModel like that can work, but the viewmodel might have a bunch of other code and application/dagger references that will not work in the preview either. The approach I am taking so far is to actually use mockk (or mockito) to mock out the viewmodel. With this approach I can 1) specify the exact state I want to test with 2) enforce that the UI only invokes unidirectional functions on the ViewModel 3) avoid issues with dagger/application objection in previews. This also allows the same composables to work in Paparazzi for screenshot testing. (Another option could be to have a composable layer where you pass just the State object and viewmodel callbacks as lambda parameters - would be more tidy and explicit, but also a bit of a pain to manage and scale.)
I have set up some scaffolding to help mock the viewmodel and setup the state to preview automatically for each viewmodel, and we have a new pattern for declaring mocks (as opposed to the Fragment based mock system). We're still building it out and validating the design, but hopefully we can share more later this year.
@elihart I'm wondering if this approach has evolved on your end and if there's a better way to access view model/state or whether or not you're hoisting state.
Our team is running into the same issue as above where if we reference the view model from a smaller composable function the Compose Preview doesn't work. We have the option of hoisting state, but we run into the risk of passing too many parameters down to the smaller Composables.
Could you also clarify your approach with using mockk
to mock out the view model? I'm not understanding how it works.
@safa007 do you know if another solution exists? As @elihart said, in my case, where viewmodel has a lot of parameters, mocking them would be a nightmare
@elihart @gpeal Do you have any suggestion or proposals to share how to resolve this issue?
Our solution is to mock the viewmodel; with that you can set the coroutine scope and state that you want returned by the viewmodel. the compose UI should only be accessing the state flow from the viewmodel, so there should be nothing else to mock. The ui will call functions on the viewmodel for event handling, but those functions can be set to be no-ops via the mocking (eg, Mockk has the relaxUnitFun
option).
You aren't going to get a functional viewmodel in a compose preview.
I have a composable that access to the mavericks view model :
As soon as I launch the design tab in Android Studio I get error, stack trace being :
I can't find anything online mentioning this error so I'm opening this issue.
Using AS Electric Eel / Compose 1.2 beta / Mavericks 2.6.0
Thanks