compose-destinations: ViewModel unit test problems with SavedStateHandle.navArgs()

Hi,

I’m using SavedStateHandle.navArgs() to get the navigation arguments on my ViewModel. However, on my Unit tests the call fails with NoClassDefFoundError: Could not initialize class error. I’ve added the value directly in my SavedStateHandle with no success.

How can I manage to test the ViewModel with the navigation arguments without having to do a UI test?

Could not initialize class com.ramcosta.composedestinations.navargs.primitives.DestinationsStringNavType
java.lang.NoClassDefFoundError: Could not initialize class com.ramcosta.composedestinations.navargs.primitives.DestinationsStringNavType

Code snippets:

ViewModel

class SearchViewModel @Inject constructor(
    savedStateHandle: SavedStateHandle,
    ...
) {

    init {
        // Test fails here
        val initialQuery = savedStateHandle.navArgs<SearchScreenNavArgs>().initialQuery
    }

Unit test

@Before
fun setup() {
    viewModel = SearchViewModel(
            savedStateHandle = SavedStateHandle().apply {
                set("initialQuery", "")
            },
            ...
    )
}

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 20 (13 by maintainers)

Most upvoted comments

This should be fixed guys @epool @luanbarbosa-sanoma please test version 1.x.20 and let me know!

Until then, use assited injection (if your framework allows it, as said above, Hilt as issues with it atm) and pass the arguments to the ViewModel (this is much better from a clean code perspective in my opinion).

If not, you can set the args from the outside with some setter.

That is the reason, yes.

I can make it a lazy initialized field, and if the tests don’t need it (it seems like that is your case) then that would work. But I still need to think more about it since what if the tests do need it? 🤔

I’ll reopen this to see if I can come up with a better solution. Thanks @epool

Hmm not sure how to mock these methods with mockito 🤔

Maybe your best bet until they fix the assisted injection in Hilt is to use a setter like you said before. If you were using manual dep injection this would be trivial, so yeah, it’s annoying that this issue is worse because Hilt is missing this support.

I closed this but I’ll be paying attention to your replies here 😃