【问题标题】:How can I test fragments with Robolectric?如何使用 Robolectric 测试碎片?
【发布时间】:2020-02-28 15:23:22
【问题描述】:

我知道有一个 Robolectric.shadowOf(Fragment) 方法和一个 ShadowFragment 类,以为它们没有在文档中列出,但我无法让它工作。

myFragment = new MyFragment();
myFragment.onCreateView(LayoutInflater.from(activity), (ViewGroup) activity.findViewById(R.id.container), null);
myFragment.onAttach(activity);
myFragment.onActivityCreated(null); 

我正在使用 API 级别 13 (Honeycomb)。

谢谢。

【问题讨论】:

    标签: android robolectric


    【解决方案1】:

    Edit #4 & #5:在Robolectric 3.*,他们拆分了片段起始函数。

    对于支持片段,您需要将dependency 添加到您的build.gradle

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

    导入:org.robolectric.shadows.support.v4.SupportFragmentTestUtil.startFragment;

    对于平台片段,您不需要此依赖项。导入:import static org.robolectric.util.FragmentTestUtil.startFragment;

    他们都使用相同的名称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 );
        }
    }
    

    编辑#3:Robolectric 2.4 有一个API for support and regular fragments。您可以使用newInstance() 模式或在构造Fragment 时使用构造函数。

    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 );
        }
    }
    

    编辑#2:如果您正在使用支持片段 (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 );
    }
    

    编辑:如果您升级到 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();
    }
    

    原答案

    正如其他评论者所建议的那样,您确实需要使用片段管理器(而不是调用您上面列出的生命周期方法)。

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

    我创建了一个测试运行器,并有一个为我启动片段的函数,因此我可以在任何地方使用它。

    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();
        }
    }
    

    【讨论】:

    • 你能证明上面确实调用了片段的生命周期函数如onCreateView吗?在此之后,我的片段不为空,但我的片段中需要 onCreateView 的成员仍然是。
    • 我会使用调试器来验证是否调用了生命周期方法。也许片段还有另一个问题。查看此示例以测试片段中的视图元素:github.com/colabug/Animation/blob/master/src/test/java/com/…(主项目:github.com/colabug/Animation
    • 感谢您的示例,玩弄了您的项目并确认确实调用了 onCreateView,因此正如您所说,我的代码一定有其他问题。
    • 鉴于上面的 startFragment(...) 是静态的并且没有引用任何字段,它似乎更像是你在 TestUtils 类中而不是 TestRunner 中的东西..?
    • startFragment 似乎可用于 org.robolectric.util.FragmentTestUtil 中的 robolectric 2.x
    【解决方案2】:

    你们都在努力做到这一点。只需使用 FragmentTestUtil。

    FragmentTestUtil.startFragment(yourfragment);
    

    【讨论】:

    • 这是一个相对较新的调用,它仅在您使用支持库片段 FWIW 时才有效。
    • 看起来他们将课程扩展到支持和不支持的片段 (github.com/robolectric/robolectric/blob/master/src/main/java/…)
    • 如果你想测试需要Fragment 可见的东西,你需要调用ActivityController.of(yourFragment.getActivity()).visible()。当我试图验证我的FragmentonCreateOptionsMenu 是否被正确调用时,这给我带来了麻烦。在父活动上添加对visible() 的调用使其正常工作。
    • 或者您可以直接使用FragmentTestUtil.startVisibleFragment()
    • Robolectric.buildFragment() 是最新版本
    【解决方案3】:

    支持片段已移至模块:

    shadows-support-v4

    (截至 2015 年 7 月,Robolectric v3.0)

    向 app/build.gradle 添加 gradle 依赖项:

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

    然后导入您的 Robolectric 测试 java 类:

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

    然后您可以开始并使用 support-v4 片段进行测试:

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

    参考资料:

    【讨论】:

    • 谢谢,今天早上很难解决这个问题,然后更新了答案。
    【解决方案4】:

    我很确定你必须使用FragmentManager 创建一个FragmentTransaction,然后它才能工作。

    【讨论】:

      【解决方案5】:

      我只是想在 Robolectric 2.0 中添加它,即使在这样做之后:

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

      它仍然为我返回 null。我所做的是添加activity.getSupportFragmentManager().executePendingTransaction();,它起作用了。

      似乎 robolectric 出于某种原因没有运行它。似乎 Looper 已暂停或其他什么。这对我有用的任何方式,它看起来像这样:

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

      【讨论】:

        【解决方案6】:

        旧的 android 片段已经被弃用,似乎支持片段很快也会被弃用。要测试 androidx 片段,您可以使用带有 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)
        }
        

        【讨论】:

        • 我们如何将 Robolectric 与 Fragment 场景一起使用?
        【解决方案7】:
        SupportFragmentTestUtil.startFragment(fragment, AppCompatActivity::class.java)
        

        如果活动正在扩展AppCompatActivity

        这是使用 Kotlin

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-12-11
          • 1970-01-01
          • 2013-08-19
          • 2012-10-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多