5

我为实例化片段(实际上是选项卡)的 Activity 编写了 Android JUnit 测试。在测试期间,当我尝试对这些选项卡执行任何操作时,它们会崩溃,因为它们中的 getActivity() 方法返回 null。实际的应用程序(不是测试)永远不会显示这种行为,并且片段 getActivity() 总是在那里返回正确的父活动。我的测试用例如下所示:

public class SetupPanelTest extends ActivityUnitTestCase<MyAct> {

    FSetup s;   

    public SetupPanelTest() {
    super(MyAct.class);
    }

    protected void setUp() throws Exception {
        super.setUp();
        startActivity(new Intent(), null, null);
        final MyAct act = getActivity();

        AllTabs tabs = act.getTabs();
        String tabname = act.getResources().getString(R.string.configuration);

        // This method instantiates the activity as said below
        s = (FSetup) tabs.showTab(tabname);
        FragmentManager m = act.getFragmentManager();
        // m.beginTransaction().attach(s).commit(); 
        //     ... and even this does not help when commented out

        assertTrue(s instanceof FSetup);  // Ok     
        assertEquals(act, s.getActivity()); // Failure
    }

    public void testOnPause() {
        // this crashes because s.getActivity == null;
        s.onPause();
        }
 }

AllTabs 以这种方式创建一个片段,然后是必需的:

 FragmentManager manager = getFragmentManager();
 Fragment fragment = manager.findFragmentByTag(tabname);
 if (fragment == null || fragment.getActivity() == null) {
      Log.v(TAG, "Instantiating ");
      fragment = new MyFragment();
      manager.beginTransaction().replace(R.id.setup_tab, fragment, tabname).commit();
 ....

在这里,所有片段最初都是占位符,后来被实际片段替换:

<FrameLayout
  android:id="@+id/setup_tab"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent" />    

logcat 显示新片段已被实例化。在同一个布局中,还有前面提到的 AllTabs 片段似乎没有这个问题(否则它在哪里以及如何获取 FragmentManager):

<TabWidget
     android:id="@android:id/alltabs"
...

Most impressively, when I call attach directly on the fragment manager obtained on the right activity, this still has no effect. I tried to put five seconds delay (I have read that transaction may be delayed), I tried to call the rest of the test through runOnUiThread - nothing helps.

The question is that is need to do so to attach my fragments to the activity also during the test. I have fragment and I have activity, I cannot attach one to another.

4

1 回答 1

9

Even if you call .commit() on transaction, it is still not done, fragments are attached only lazily.

    FragmentManager m = activity.getFragmentManager();
    m.executePendingTransactions();

This finally attaches all fragments to the activity. Seems redundant when running the application itself but required in JUnit test case.

于 2013-01-14T09:51:08.577 回答