如何使 ActivityUnitTestCase 中的片段的 isResumed() return 为真?

How to make isResumed() return true for a Fragment in an ActivityUnitTestCase?

我写了一个片段 class,在某个时候,在执行某事之前会仔细检查 isResumed()。我想编写测试以确保此代码运行。但是,在我从 ActivityUnitTestCase 派生的测试用例中,isResumed() 似乎总是 return false。在这样的测试中有什么方法可以使它 return true 吗?我正在使用支持库的片段 classes.

这是一个示例测试,它使用与我的实际测试使用的代码类似的代码,并演示了问题。 testIsResumed() 总是失败,因为 isResumed() 是假的,尽管在 activity 和片段上都调用了 onStart()onResume(),并且 [=21= 的自由使用]:

public class FragmentIsResumedTest
        extends ActivityUnitTestCase<FragmentIsResumedTest.TestActivity> {
    public static class TestFragment
            extends android.support.v4.app.Fragment {
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            return new LinearLayout(getContext());
        }
    }

    public static class TestActivity
            extends android.support.v4.app.FragmentActivity {
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(new LinearLayout(this));
        }
    }

    public FragmentIsResumedTest() {
        super(TestActivity.class);
    }

    public void testIsResumed() {
        startActivity(
                new Intent(
                        getInstrumentation().getTargetContext(),
                        TestActivity.class),
                null, null);
        getInstrumentation().waitForIdleSync();
        TestActivity activity = getActivity();
        TestFragment fragment = new TestFragment();
        fragment.onCreate(null);
        getInstrumentation().callActivityOnStart(activity);
        activity.getSupportFragmentManager().beginTransaction()
                .add(android.R.id.content, fragment, "FragmentTag")
                .commit();
        getInstrumentation().callActivityOnResume(activity);
        fragment.onStart();
        fragment.onResume();
        getInstrumentation().waitForIdleSync();
        activity.getSupportFragmentManager().executePendingTransactions();
        getInstrumentation().waitForIdleSync();

        assertTrue(fragment.isResumed());
    }
}

如何在从 ActivityUnitTestCase 扩展的单元测试中使 isResumed() 为真?

缺少的是问题中的测试设置从不调用 Activity.onPostResume()。在Support Library的FragmentActivitythis is where the fragments are resumed from, by calling dispatchResume() on the FragmentManager. Simply calling Fragment.onResume() manually won't cause isResumed() to return true. And for some reason, Instrumentation.callActivityOnResume() never calls onPostResume()中并没有对应的callActivityOnPostResume().

一个简单的解决方法是在 TestActivity 中制作 onPostResume() public:

public static class TestActivity
        extends android.support.v4.app.FragmentActivity {
    @Override
    public void onPostResume() {
        super.onPostResume();
    }

    /* ... */
}

并在测试设置中 callActivityOnResume() 之后的某个时间调用它。这似乎处理了所有未决的片段事务,因此不再需要 executePendingTransactions()。即使在删除了对 waitForIdleSync() 的所有调用之后,以下测试代码对我仍然有效。使用 Mockito.spy(),我们可以看到片段上的所有生命周期方法都被调用了:

TestActivity activity = getActivity();
TestFragment fragment = spy(new TestFragment());
getInstrumentation().callActivityOnStart(activity);
activity.getSupportFragmentManager().beginTransaction()
        .add(android.R.id.content, fragment, "FragmentTag")
        .commit();
getInstrumentation().callActivityOnResume(activity);
activity.onPostResume();

assertTrue(fragment.isResumed());
InOrder inOrder = inOrder(fragment);
inOrder.verify(fragment).onCreate(any(Bundle.class));
inOrder.verify(fragment).onViewCreated(any(View.class), any(Bundle.class));
inOrder.verify(fragment).onActivityCreated(any(Bundle.class));
inOrder.verify(fragment).onStart();
inOrder.verify(fragment).onResume();