How can I test fragments with Robolectric?

后端 未结 7 1088
萌比男神i
萌比男神i 2020-12-02 10:16

I know there is a Robolectric.shadowOf(Fragment) method and a ShadowFragment class, thought they aren\'t listed on the docs, but I can\'t make it w

相关标签:
7条回答
  • 2020-12-02 10:47

    Edit #4 & #5: In Robolectric 3.*, they split up the fragment starting functions.

    For support fragments, you will need to add a dependency to your build.gradle:

    testCompile "org.robolectric:shadows-supportv4:3.8"
    

    Import: org.robolectric.shadows.support.v4.SupportFragmentTestUtil.startFragment;

    For platform fragments, you don't need this dependency. Import: import static org.robolectric.util.FragmentTestUtil.startFragment;

    They both use the same name of startFragment().

    import static org.robolectric.shadows.support.v4.SupportFragmentTestUtil.startFragment;
    
    @RunWith(RobolectricTestRunner.class)
    @Config(constants = BuildConfig.class)
    public class YourFragmentTest
    {
        @Test
        public void shouldNotBeNull() throws Exception
        {
            YourFragment fragment = YourFragment.newInstance();
            startFragment( fragment );
            assertNotNull( fragment );
        }
    }
    

    Edit #3: Robolectric 2.4 has an API for support and regular fragments. You can either use the newInstance() pattern or use the constructor when constructing your Fragment's.

    import org.junit.Test;
    import org.junit.runner.RunWith;
    import static org.junit.Assert.assertNotNull;
    import static org.robolectric.util.FragmentTestUtil.startFragment;
    
    @RunWith(RobolectricGradleTestRunner.class)
    public class YourFragmentTest
    {
        @Test
        public void shouldNotBeNull() throws Exception
        {
            YourFragment fragment = new YourFragment();
            startFragment( fragment );
            assertNotNull( fragment );
        }
    }
    

    Edit #2: There's a new helper if you're using support fragments (one that supports regular activities/fragments should be in the next release):

    import static org.robolectric.util.FragmentTestUtil.startFragment;
    
    @Before
    public void setUp() throws Exception
    {
        fragment = YourFragment.newInstance();
        startFragment( fragment );
    }
    

    Edit: If you upgraded to Robolectric 2.0:

    public static void startFragment( Fragment fragment )
    {
        FragmentActivity activity = Robolectric.buildActivity( FragmentActivity.class )
                                               .create()
                                               .start()
                                               .resume()
                                               .get();
    
        FragmentManager fragmentManager = activity.getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.add( fragment, null );
        fragmentTransaction.commit();
    }
    

    Original answer

    As the other commenter suggested, you do need to use the fragment manager (instead of calling the lifecycle methods you listed above).

    @RunWith(MyTestRunner.class)
    public class YourFragmentTest
    {
        @Test
        public void shouldNotBeNull() throws Exception
        {
            YourFragment yourFragment = new YourFragment();
            startFragment( yourFragment );
            assertNotNull( yourFragment );
        }
    

    I create a test runner and have a function that starts up a fragment for me so I can use it everywhere.

    public class MyTestRunner extends RobolectricTestRunner
    {
        public MyTestRunner( Class<?> testClass ) throws InitializationError
        {
            super( testClass );
        }
    
        public static void startFragment( Fragment fragment )
        {
            FragmentManager fragmentManager = new FragmentActivity().getSupportFragmentManager();
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            fragmentTransaction.add( fragment, null );
            fragmentTransaction.commit();
        }
    }
    
    0 讨论(0)
  • 2020-12-02 10:50
    SupportFragmentTestUtil.startFragment(fragment, AppCompatActivity::class.java)
    

    If the activity is extending AppCompatActivity

    This is using Kotlin

    0 讨论(0)
  • 2020-12-02 10:53

    Old android fragments are already deprecated, seems like support fragments soon will be deprecated too. To test androidx fragments you can use fragment scenarios with robolectric https://developer.android.com/training/basics/fragments/testing

    testImplementation 'androidx.fragment:fragment-testing:1.2.2'
    
    val scenario = launchFragmentInContainer<MyFragment>()
    scenario.onFragment { fragment ->
        assertNotNull(fragment.view.synteticInflatedView)
    }
    
    0 讨论(0)
  • 2020-12-02 11:03

    I just wanted to add that in Robolectric 2.0 even after doing:

    activity = Robolectric.buildActivity(FragmentActivity.class).create().start().resume().get();
    fragment.show(activity.getSupportFragmentManager(), null);
    fragment.getDialog();  //This stills returns null
    

    It still returned null for me. what I did was to add activity.getSupportFragmentManager().executePendingTransaction(); and it worked.

    It seems robolectric doesn't run this for some reason. it seems that maybe the Looper is paused or something. any way this worked for me and it looks like this:

    activity = Robolectric.buildActivity(FragmentActivity.class).create().start().resume().get();
    fragment.show(activity.getSupportFragmentManager(), null);
    activity.getSupportFragmentManager().executePendingTransactions();
    fragment.getDialog();
    
    0 讨论(0)
  • 2020-12-02 11:05

    I'm pretty sure you have to create a FragmentTransaction using the FragmentManager, then it will work.

    0 讨论(0)
  • 2020-12-02 11:06

    Support fragments have been moved to module:

    shadows-support-v4

    (as of July,2015, Robolectric v3.0)

    Add a gradle dependency to app/build.gradle:

    testCompile 'org.robolectric:shadows-support-v4:3.0'
    

    Then import to your Robolectric test java class:

    import org.robolectric.shadows.support.v4.SupportFragmentTestUtil;
    

    Then you can start & use a support-v4 fragment for testing:

    @Test
    public void minimalFragmentTest() throws Exception {
        MyFunFragment fragment = new MyFunFragment();
        SupportFragmentTestUtil.startVisibleFragment(fragment);
        assertThat(fragment.getView()).isNotNull();
    }
    

    References:

    • github changelog, moving support fragments to different module
    0 讨论(0)
提交回复
热议问题