Search code examples
android-testingandroid-jetpack-navigationandroid-fragmentscenario

Fragment testing, I'm missing something equivalent to ActivityScenarioRule


I'm used to test my Fragments by launching the Activity containing it in an Espresso test. This has been working pretty nicely and I have been able to control the test environment/execution through some test rules (e.g. OkHttpIdlingResourceRule) that are added to ActivityScenarioRule (or IntentsTestRule) which is then used to launch the Activity.

Now that that I'm moving towards single Activity approach and utilizing also Navigation component I would like to start testing my Fragments in isolation. However, to be able to do that I would need similar capabilities on Fragment testing as do exists in Activity testing. ActivityScenarioRule implements TestRule but FragmentScenario does not and the is no FragmentScenarioRule.

Am I missing something?


Solution

  • It's actually pretty simple. When testing Activities I had a base test class containing the following:

    @Rule @JvmField
    val activityRule: IntentsTestRule<*>
    
    @Rule @JvmField
    val chain: RuleChain
    
    init {
        activityRule = IntentsTestRule(
                activityClass,
                true, // true if the Activity should be placed into "touch mode" when started
                false) // launchActivity
    
        var initChain = RuleChain.outerRule(firstRule)
                .around(OkHttpIdlingResourceRule())
                .around(activityRule) 
    
        for (rule in additionalTestRules) {
            initChain = initChain.around(rule)
        }
    
        chain = initChain
    }
    

    In the test the Activity is launched with activityRule.launchActivity(null) And now when testing Fragments this becomes:

    @Rule
    @JvmField
    val chain: RuleChain
    
    init {
        var initChain = RuleChain.outerRule(firstRule)
                .around(OkHttpIdlingResourceRule())
    
        for (rule in additionalTestRules) {
            initChain = initChain.around(rule)
        }
    
        chain = initChain
    }
    

    In the test Fragment is launched with launchFragmentInContainer()