如何使isResumed()为ActivityUnitTestCase中的片段返回true?

时间:2016-06-04 19:05:17

标签: java android android-fragments android-lifecycle android-testing

我编写了一个片段类,在某一点上,在执行某些操作之前,双重检查isResumed()。我想编写测试来确保此代码运行。但是,在我从ActivityUnitTestCase派生的测试用例中,isResumed()似乎总是返回false。有没有办法让它在这样的测试中返回true?我正在使用支持库的片段类。

这是一个示例测试,它使用与我的实际测试使用类似的代码,并演示了这个问题。 testIsResumed()始终失败,因为isResumed()为false,尽管已对活动和片段调用了onStart()onResume(),以及waitForIdleSync()的自由使用:

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

如何在isResumed()扩展的单元测试中为我的片段设置ActivityUnitTestCase为真?

1 个答案:

答案 0 :(得分:0)

缺少的是问题中的测试设置从不调用Activity.onPostResume()。在支持资源库FragmentActivitythis is where the fragments are resumed from中,致电FragmentManager上的dispatchResume()。简单地手动调用Fragment.onResume()不会导致isResumed()返回true。出于某种原因,Instrumentation.callActivityOnResume() never calls onPostResume(),并且没有相应的callActivityOnPostResume()

一个简单的解决方法是在onPostResume()中公开TestActivity

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