Introduction
I have a very simple application to practice fragment factory with navigation component and Koin. There are two fragments. The navigation host fragment is a fragment with a very much standard, conventional constructor without any arguments. The second fragment, the fragment under test, is called with two arguments as defined in Koin Module:
val koinModule = module {
single { Kupa }
fragment { MainNavHostFragment() }
fragment { DetailFragment(get(),null)}
}
DetailFragment is implemented as follows.
class DetailFragment(
private var kupa: Kupa,
private var registry: ActivityResultRegistry? = null
) : Fragment() {
lateinit var binding: DetailFragmentBinding
lateinit var getContent: ActivityResultLauncher<String>
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
if (registry == null) {
registry = requireActivity().activityResultRegistry
}
defineGetContent()
binding = DetailFragmentBinding.inflate(inflater,container,false)
binding.button2.setOnClickListener {
findNavController().navigate(DetailFragmentDirections.actionDetailFragmentToEntryFragment())
}
binding.button3.setOnClickListener {
openFile()
}
binding.textView.text = Kupa.number.toString()
kupa.number = Random.nextInt()
return binding.root
}
Problem with testing
I want to inject a mock of registry in DetailFragmentTest
class.
The approach which came to my mind is based on launchFragmentInContainer
and here is my problem.
If the solution wasn't based on Koin I would define factory class as an input argument, but in this case the fragment factory class definition is taken care by Koin and I cannot figure out what shall I type there. Maybe there is another approach I shall take?
Underneath is code for the test I got stuck with:
@LargeTest
@RunWith(AndroidJUnit4ClassRunner::class)
class DetailFragmentTest : KoinTest {
val expectedResult = "loremIpsum"
val testRegistry = object : ActivityResultRegistry() {
override fun <I, O> onLaunch(
requestCode: Int,
contract: ActivityResultContract<I, O>,
input: I,
options: ActivityOptionsCompat?
) {
dispatchResult(requestCode, expectedResult)
}
}
var mockModule : Module = module(override=true) {
fragment { DetailFragment(get(),null)}
}
init {
loadKoinModules(mockModule)
}
@Test
fun testFunction() {
val scenario = launchFragmentInContainer<DetailFragment>(factory = ) //Here I shall define factory if I stick to that approach
Espresso.onView(ViewMatchers.withId(R.id.button3)).perform(click())
}
}