如何Mock ViewModel以使用Jetpack Compose Preview?解决Hilt注入ViewModel预览报错问题
解决Compose Preview中无法使用Hilt注入ViewModel的问题
这个问题我之前也碰到过,确实挺头疼的——Compose Preview的沙盒环境不支持Hilt的依赖注入容器初始化,所以直接调用hiltViewModel()肯定会报错。下面给你两种最常用的解决思路,亲测有效:
方法一:给MainScreen添加可传入的ViewModel参数(推荐)
核心思路是让MainScreen不强制依赖Hilt的自动注入,而是允许外部传入ViewModel实例,这样正常运行时用默认的hiltViewModel(),预览时手动传一个mock/测试用的ViewModel。
保持原MainScreen的兼容性:
你的原代码不用大改,只是保留默认参数的同时,允许外部传入ViewModel:@Composable fun MainScreen( viewModel: MainScreenViewModel = hiltViewModel() ) { // 你的Compose UI逻辑,比如使用viewModel的状态 Text(text = viewModel.uiState.value.title) }创建Mock/测试用的ViewModel:
根据你的MainScreenViewModel的逻辑,写一个专门用于预览的子类或者直接实例化(如果依赖可以mock的话)。比如你的ViewModel有依赖,用Mockito快速mock:// 假设你的ViewModel是这样的 class MainScreenViewModel @Inject constructor( private val albumRepository: AlbumRepository ) : ViewModel() { val uiState = MutableStateFlow(AlbumUiState(albums = emptyList())) // 其他业务逻辑 } // 预览用的Mock ViewModel class MockMainScreenViewModel : MainScreenViewModel(mock()) { // 给预览提供测试数据 init { uiState.value = AlbumUiState( albums = listOf( Album(id = 1, name = "测试专辑1"), Album(id = 2, name = "测试专辑2") ) ) } }如果你的ViewModel没有复杂依赖,甚至可以直接在预览里new一个(前提是构造函数允许)。
修改Preview函数传入Mock ViewModel:
现在预览里就可以手动传入mock的实例了:@Preview(showBackground = true) @Composable fun DefaultPreview() { AlbumExpoTheme { MainScreen( viewModel = MockMainScreenViewModel() ) } }
方法二:使用ViewModelFactory(适合更复杂的场景)
如果你的ViewModel需要特定的依赖,又不想写mock子类,可以自定义一个ViewModelFactory,在预览里用它创建实例:
class PreviewMainScreenViewModelFactory : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun <T : ViewModel> create(modelClass: Class<T>): T { val mockRepo = mock(AlbumRepository::class.java) // 可以提前给mockRepo设置返回值 `when`(mockRepo.getAlbums()).thenReturn(flowOf(listOf(Album(id=1, name="测试专辑")))) return MainScreenViewModel(mockRepo) as T } } // 预览里使用Factory创建ViewModel @Preview(showBackground = true) @Composable fun DefaultPreview() { AlbumExpoTheme { val viewModel = viewModel(factory = PreviewMainScreenViewModelFactory()) MainScreen(viewModel = viewModel) } }
关键注意点
- 预览的核心是展示UI,所以Mock ViewModel只需要提供UI所需的测试状态数据即可,不用实现完整的业务逻辑。
- 不要在预览里依赖真实的数据源或复杂的依赖注入逻辑,保持预览的独立性和快速加载性。
内容的提问来源于stack exchange,提问作者barryalan2633
相关产品推荐
相关产品推荐

