简体   繁体   English

如何使用 Robolectric 测试片段?

[英]How can I test fragments with Robolectric?

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 work.我知道有一个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); 

I'm working with API level 13 (Honeycomb).我正在使用 API 级别 13(蜂巢)。

Thanks.谢谢。

Edit #4 & #5 : In Robolectric 3.* , they split up the fragment starting functions.编辑#4 和#5 :在Robolectric 3.*中,他们拆分了片段起始函数。

For support fragments, you will need to add a dependency to your build.gradle :对于支持片段,您需要向build.gradle添加依赖项:

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

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

For platform fragments, you don't need this dependency.对于平台片段,您不需要此依赖项。 Import: import static org.robolectric.util.FragmentTestUtil.startFragment;导入: import static org.robolectric.util.FragmentTestUtil.startFragment;

They both use the same name of 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 );
    }
}

Edit #3 : Robolectric 2.4 has an API for support and regular fragments .编辑 #3 :Robolectric 2.4 有一个用于支持和常规片段的 API You can either use the newInstance() pattern or use the constructor when constructing your Fragment 's.您可以使用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 );
    }
}

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 ):编辑#2 :如果您使用的是支持片段,则有一个新的助手( 支持常规活动/片段的助手应该在下一个版本中):

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

You guys are all doing this the hard way.你们都在用艰难的方式做这件事。 Just use FragmentTestUtil.只需使用 FragmentTestUtil。

FragmentTestUtil.startFragment(yourfragment);

Support fragments have been moved to module:支持片段已移至模块:

shadows-support-v4阴影支持-v4

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

Add a gradle dependency to app/build.gradle:将 gradle 依赖添加到 app/build.gradle:

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

Then import to your Robolectric test java class:然后导入到您的 Robolectric 测试 java 类:

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

Then you can start & use a support-v4 fragment for testing:然后您可以开始并使用 support-v4 片段进行测试:

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

References:参考:

Old android fragments are already deprecated, seems like support fragments soon will be deprecated too.旧的 android 片段已经被弃用,似乎支持片段也很快就会被弃用。 To test androidx fragments you can use fragment scenarios with robolectrichttps://developer.android.com/training/basics/fragments/testing要测试 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)
}

I'm pretty sure you have to create a FragmentTransaction using the FragmentManager , then it will work.我很确定您必须使用FragmentManager创建一个FragmentTransaction ,然后它才能工作。

I just wanted to add that in Robolectric 2.0 even after doing:我只是想在 Robolectric 2.0 中添加:

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();我所做的是添加activity.getSupportFragmentManager().executePendingTransaction(); and it worked.它奏效了。

It seems robolectric doesn't run this for some reason.由于某种原因,robolectric 似乎没有运行它。 it seems that maybe the Looper is paused or something.似乎 Looper 可能暂停了或其他什么。 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();
SupportFragmentTestUtil.startFragment(fragment, AppCompatActivity::class.java)

If the activity is extending AppCompatActivity如果活动正在扩展AppCompatActivity

This is using Kotlin这是使用 Kotlin

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM