是否可以模拟片段内部的 ViewModel
Is there away to mock ViewModel that is inside of a fragment
有没有办法模拟在片段内部构建的 ViewModel?我正在尝试 运行 对片段进行一些测试,其中一个片段函数与 ViewModel 交互,我想 运行 测试函数并为 ViewModel 提供模拟结果。这甚至可能吗?
我的片段
class MyFragment : Fragment() {
@Inject
lateinit var viewModel: MyViewModel
override fun onCreate(savedInstanceState: Bundle?) {
(requireActivity().application as MyApplication).appComponent.inject(this)
super.onCreate(savedInstanceState)
}
}
测试
@RunWith(RoboeltricTestRunner::) {
@Before
fun setup() {
FragmentScenario.Companion.launchIncontainer(MyFragment::class.java)
}
}
是的,只需标记您的 ViewModel
open
,然后您就可以在其上创建一个模拟实现。
open class MyViewModel: ViewModel() {
fun myMethodINeedToMock() {
}
}
class MockMyViewModel: MyViewModel() {
override fun myMethodINeedToMock() {
// don't call super.myMethodINeedToMock()
}
}
因此,在测试时将您的 MockMyViewModel
注册到 DI 框架。
我想我会 post 为其他正在努力寻找解决方案的人提供此信息。您需要使用依赖于 ViewModel 的片段工厂。将 ViewModel 注入片段构造函数允许 ViewModel 轻松被模拟。需要为 FragmentFactory 完成几个步骤,但只要完成几个步骤就不会那么复杂。
- Fragment 将 ViewModel 添加到构造函数中。
class MyFragment(private val viewModel: ViewModel) : Fragment {
...
}
- FragmentFactory,允许片段在构造函数中具有依赖性。
class MyFragmentFactory(private val viewModel: MyViewModel) : FragmentFactory() {
override fun instantiate(classLoader: ClassLoader, className: String): Fragment {
return when(className) {
MyFirstFragment::class.java.name -> {
MyFragment(viewModel)
}
// You could use this factory for multiple Fragments.
MySecondFragment::class.java.name -> {
MySecondFragment(viewModel)
}
// You also don't have to pass the dependency
MyThirdFragment::class.java.name -> {
MyThirdFragment()
}
else -> super.instantiate(classLoader, className)
}
}
}
- 主要Activity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// Create your ViewModel
val viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
// create the FragmentFactory and the viewModel dependency.
supportFragmentManager.fragmentFactory = MainFragmentFactory(viewModel)
// FragmentFactory needs to be created before super in an activity.
super.onCreate(savedInstanceState)
}
}
- 测试
@RunWith(RobolectricTestRunner::class)
class MyFragmentUnitTest {
@Before
fun setup() {
val viewModel: MainViewModel = mock(MyViewModel::class.java)
...
}
}
有没有办法模拟在片段内部构建的 ViewModel?我正在尝试 运行 对片段进行一些测试,其中一个片段函数与 ViewModel 交互,我想 运行 测试函数并为 ViewModel 提供模拟结果。这甚至可能吗?
我的片段
class MyFragment : Fragment() {
@Inject
lateinit var viewModel: MyViewModel
override fun onCreate(savedInstanceState: Bundle?) {
(requireActivity().application as MyApplication).appComponent.inject(this)
super.onCreate(savedInstanceState)
}
}
测试
@RunWith(RoboeltricTestRunner::) {
@Before
fun setup() {
FragmentScenario.Companion.launchIncontainer(MyFragment::class.java)
}
}
是的,只需标记您的 ViewModel
open
,然后您就可以在其上创建一个模拟实现。
open class MyViewModel: ViewModel() {
fun myMethodINeedToMock() {
}
}
class MockMyViewModel: MyViewModel() {
override fun myMethodINeedToMock() {
// don't call super.myMethodINeedToMock()
}
}
因此,在测试时将您的 MockMyViewModel
注册到 DI 框架。
我想我会 post 为其他正在努力寻找解决方案的人提供此信息。您需要使用依赖于 ViewModel 的片段工厂。将 ViewModel 注入片段构造函数允许 ViewModel 轻松被模拟。需要为 FragmentFactory 完成几个步骤,但只要完成几个步骤就不会那么复杂。
- Fragment 将 ViewModel 添加到构造函数中。
class MyFragment(private val viewModel: ViewModel) : Fragment {
...
}
- FragmentFactory,允许片段在构造函数中具有依赖性。
class MyFragmentFactory(private val viewModel: MyViewModel) : FragmentFactory() {
override fun instantiate(classLoader: ClassLoader, className: String): Fragment {
return when(className) {
MyFirstFragment::class.java.name -> {
MyFragment(viewModel)
}
// You could use this factory for multiple Fragments.
MySecondFragment::class.java.name -> {
MySecondFragment(viewModel)
}
// You also don't have to pass the dependency
MyThirdFragment::class.java.name -> {
MyThirdFragment()
}
else -> super.instantiate(classLoader, className)
}
}
}
- 主要Activity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// Create your ViewModel
val viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
// create the FragmentFactory and the viewModel dependency.
supportFragmentManager.fragmentFactory = MainFragmentFactory(viewModel)
// FragmentFactory needs to be created before super in an activity.
super.onCreate(savedInstanceState)
}
}
- 测试
@RunWith(RobolectricTestRunner::class)
class MyFragmentUnitTest {
@Before
fun setup() {
val viewModel: MainViewModel = mock(MyViewModel::class.java)
...
}
}