I recently had to add test coverage to a class that has a hard, transiant dependency on FragmentManager
via FragmentStateViewPager
and its use of fragment transaction internally. After stepping through the source I find it impossible to use Mokito to mock()
, so I started looking for a way to use a real FragmentManager
in my test. At first I thought I need to actually create an hosting Activity
and write the test as an instrumentation test, however a fellow android engineer @heathborders gave me the hint to take a look at the approach FragmentScenario
use, so I am going to document the approach I used here.
This is written from memory, without compiler help, so it probably won’t compile and won’t match your environment.
@RunWith(RobolectricRunner::class)
class MyTest {
internal class DummyFragment: Fragment()
private val fragmentScenario = FragmentScenario.launchInContainer(DummyFragment::class.java)
@Before
fun setUp() {
fragmentScenario.recreate()
fragmentScenario.onFragment { frag ->
val fragManager = frag.parentFragmentManager
// use fragManager in your test object setup
}
}
}
How does this work? FragmentScenario
has a internal empty FragmentActivity
that supplies the Fragment
s it hosts with a real FragmentManager
, so by using a dummy empty Fragment
we are able to make use of the FragmentManager
instance. And bonus point of using FragmentScenario
is you can control the lifecycle state by using moveToState()
which can help recreate some hard-to-recreate situations in Fragment
/Activity
lifecycle.
Hope this article can save someone two nights of sleep.