2

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())
    }
}
Kape
  • 195
  • 1
  • 8

0 Answers0