android – Robolectric:如何测试包含SherlockFragment的活动?

我一直在这里阅读很多链接,github和robolectric博客,但还没找到可行的解决方案(已经使用Robolectric 2.0 alpha 2).

更新:即使我们为android.support.v4.app.Fragment替换SherlockFragment,问题也会发生.

在跟踪这个tip之后,我能够测试一个SherlockFragmentActivity,但是当我将这个片段添加到我的活动xml时,这是一个SherlockFragment:

<fragment 
    android:name="com.marcelopazzo.fragmentapplication.ExampleFragment" 
    android:id="@+id/example_fragment"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" />

SherlockFragment类:

public class ExampleFragment extends SherlockFragment {

    @Override
    public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {
        return inflater.inflate(R.layout.example_fragment,container,false);
    }
}

这是片段膨胀的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/hello_again"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_again" />

</LinearLayout>

我收到以下错误

java.lang.NullPointerException
    at org.robolectric.shadows.ShadowViewGroup.addView(ShadowViewGroup.java:69)
    at android.view.ViewGroup.addView(ViewGroup.java)
    at org.robolectric.res.builder.LayoutBuilder.constructFragment(LayoutBuilder.java:150)
    at org.robolectric.res.builder.LayoutBuilder.create(LayoutBuilder.java:104)
    at org.robolectric.res.builder.LayoutBuilder.doInflate(LayoutBuilder.java:42)
    at org.robolectric.res.builder.LayoutBuilder.doInflate(LayoutBuilder.java:45)
    at org.robolectric.res.builder.LayoutBuilder.inflateView(LayoutBuilder.java:62)
    at org.robolectric.shadows.ShadowLayoutInflater.inflate(ShadowLayoutInflater.java:50)
    at org.robolectric.shadows.ShadowLayoutInflater.inflate(ShadowLayoutInflater.java:55)
    at android.view.LayoutInflater.inflate(LayoutInflater.java)
    at com.squareup.test.ActionBarSherlockRobolectric.setContentView(ActionBarSherlockRobolectric.java:38)
    at com.actionbarsherlock.app.SherlockFragmentActivity.setContentView(SherlockFragmentActivity.java:262)
    at com.marcelopazzo.fragmentapplication.MainActivity.onCreate(MainActivity.java:13)
    at com.marcelopazzo.fragmentapplication.MainActivityTest.setUp(MainActivityTest.java:33)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27)
    at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:110)
    at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
    at org.junit.runners.BlockJUnit4ClassRunner.runchild(BlockJUnit4ClassRunner.java:71)
    at org.junit.runners.BlockJUnit4ClassRunner.runchild(BlockJUnit4ClassRunner.java:49)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runchildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:234)
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:133)
    at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:114)
    at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:188)
    at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:166)
    at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:86)
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:101)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:74)

这是我正在使用的测试类:

@RunWith(RobolectricTestRunner.class)
public class MainActivityTest {

    private MainActivity activity;
    private TextView textView;

    public static final String GREETINGS = "Hello World!";  

    @Before
    public void setUp() {

        ActionBarSherlock.registerImplementation(ActionBarSherlockRobolectric.class);
        ActionBarSherlock.unregisterImplementation(ActionBarSherlockNative.class);
        ActionBarSherlock.unregisterImplementation(ActionBarSherlockCompat.class);

        activity = new MainActivity();
        activity.onCreate(null);

        textView = (TextView) activity.findViewById(R.id.hello);
    }

    @Test
    public void shouldGreet() {
        assertEquals(GREETINGS,textView.getText());
    }
}

该应用程序在设备上正常工作.

在这里错过了什么?

ps:完整的源代码可在github获得

编辑:还使用square / master(2.0 alpha 3 square 5)分支的代码进行测试,并得到了同样的问题.
检查LayoutBuilder.constructFragment,我认为问题是activity.getSupportFragmentManager().beginTransaction().add(fragment,tag).commit()不能使用SherlockFragment,因此fragment.getView()返回null.

我不确定我是否可以做任何事来解决这个问题……我已经在检查是否可以在robolectric上修复它,如果有人对此有任何提示,请告诉我.

解决方法

您可以尝试使用Robolectric 2.0的新ActivityController,它修复了一些经常出现的调度/操作顺序问题.
MainActivity activity = Robolectric.buildActivity(MainActivity.class)
                                    .create().get();

调用onCreate()期间,它会安排主循环器暂时暂停.

相关文章

Android性能优化——之控件的优化 前面讲了图像的优化,接下...
前言 上一篇已经讲了如何实现textView中粗字体效果,里面主要...
最近项目重构,涉及到了数据库和文件下载,发现GreenDao这个...
WebView加载页面的两种方式 一、加载网络页面 加载网络页面,...
给APP全局设置字体主要分为两个方面来介绍 一、给原生界面设...
前言 最近UI大牛出了一版新的效果图,按照IOS的效果做的,页...