如何使用Robolectric测试碎片?

59
我知道有一个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(蜂巢)。

谢谢。

7个回答

114
Edit #4 & #5: 在 Robolectric 3.* 版本中,他们将片段启动函数进行了拆分。
对于支持片段,您需要在 build.gradle 中添加 dependency
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。您可以使用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:如果您正在使用支持片段(一个支持常规活动/片段的将在下一个版本中发布),则会有一个新的助手可用:

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

1
你能证明上述代码确实调用了片段的生命周期函数,例如onCreateView吗?在此之后,我的片段不为空,但需要onCreateView的成员仍然为空。 - brk3
@android.weasel 此外,通常您会向测试运行器添加更多功能。 请查看以下链接以获取更多信息:http://blog.chariotsolutions.com/2012/08/android-unit-testing-with-robolectric.html - colabug
@EugenMartynov 我还没有迁移。你有可以分享的新方法解决方案吗? - colabug
@EugenMartynov 我刚刚完成了调试,当我将一个bundle传递给Fragment时出现了相同的错误消息。确保尝试使用纯净/新/空白fragment来确保它不是与您的fragment有关的奇怪问题。 - colabug
1
似乎在org.robolectric.util.FragmentTestUtil中,startFragment可用于robolectric 2.x。 - Somatik
显示剩余13条评论

37

你们都在用最困难的方式去做这件事情。只需要使用FragmentTestUtil即可。

FragmentTestUtil.startFragment(yourfragment);

1
这是一个相对较新的调用,只有在使用支持库片段时才有效,顺便说一下。 - user153275
看起来他们扩展了该类以支持和不支持Fragments (https://github.com/robolectric/robolectric/blob/master/src/main/java/org/robolectric/util/FragmentTestUtil.java)。 - Maragues
7
如果你想测试需要Fragment可见的内容,那么你需要调用ActivityController.of(yourFragment.getActivity()).visible()。当我尝试验证我的FragmentonCreateOptionsMenu是否被正确调用时,这让我陷入了麻烦。在父活动中添加对visible()的调用使它正常工作。 - user1978019
2
或者你可以直接使用FragmentTestUtil.startVisibleFragment() - Jaydeep Solanki
2
Robolectric.buildFragment() 是最新版本。 - narancs
显示剩余2条评论

15

支持片段已被移动到模块:

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

参考资料:

  • Github日志,将支持Fragment的模块移动到不同的模块中

谢谢,今天早上我通过艰难的方式弄清楚了这个问题,然后更新了答案。 - colabug

4

旧版的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)
}

1
我们如何在Fragment场景中使用Robolectric? - Bills

2

我相信您必须使用FragmentManager创建一个FragmentTransaction,然后它才会起作用。


2

我想补充一下,在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();

1
SupportFragmentTestUtil.startFragment(fragment, AppCompatActivity::class.java)

如果该活动正在扩展AppCompatActivity,则使用Kotlin。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接