使用Robolectric测试启动活动的代码

10

我有一些代码想要用Robolectric进行测试。基本上,我想测试当点击一个按钮时是否会启动一个活动。

HomeScreenFragment.java:

public class HomeScreenFragment extends Fragment {

    private Button mSignInButton;

    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState); // call to super class
    }

    @Override
    public View onCreateView(LayoutInflater inflater,
                             ViewGroup parent,
                             Bundle savedInstanceState){

        // inflate view
        View view = inflater.inflate(R.layout.fragment_home_screen, parent, false);

        // handle sign in button
        mSignInButton = (Button)view.findViewById(R.id.sign_in_button);
        mSignInButton.setOnClickListener(new View.OnClickListener() {
            // anonymous inner class
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(getActivity(), SignInActivity.class);// start sign in activity with intent
                startActivity(intent); // <<== ERROR HERE WHEN RUNNING TEST

            }
        }
    }
}

我的测试看起来像这样: HomeScreenFragmentTest.java:

@RunWith(RobolectricTestRunner.class)
public class HomeScreenFragmentTest {

    private Activity mHomeScreenActivity;
    private Fragment mTestFragment;
    private Button mSignInButton;

    @Before
    public void setup() throws Exception{

        mHomeScreenActivity = Robolectric.buildActivity(HomeScreenActivity.class).create().get(); // start HomeScreenActivity, call through to onCreate()
        mTestFragment = mHomeScreenActivity.getFragmentManager().findFragmentById(R.id.home_screen_fragment_container);// get HomeScreenFragment

        // run onCreateView
        View testView = mTestFragment.onCreateView(LayoutInflater.from(mHomeScreenActivity),
                (ViewGroup) mHomeScreenActivity.findViewById(R.id.home_screen_fragment_container),
                null);

        // get button view
        mSignInButton = (Button)testView.findViewById(R.id.sign_in_button);

    }

    // clicking sign in button should launch SignInActivity
    @Test
    public void testSignInButton2() throws Exception{
        mSignInButton.performClick(); <<=== ERROR STARTS HERE
        ShadowActivity shadowActivity = Robolectric.shadowOf(mHomeScreenActivity); // create shadow activity
        Intent startedIntent = shadowActivity.getNextStartedActivity();            // get intent of next activity on stack
        ShadowIntent shadowIntent = Robolectric.shadowOf(startedIntent);            // create shadow intent which starts next activity
        assertEquals(SignInActivity.class.getName(), shadowIntent.getComponent().getClassName()); // compare shadow intent w/ desired next activity
    }

我遇到的问题与测试有关。代码在模拟器/设备上本身运行良好。但问题在于当Robolectric运行performClick()方法,并且到达onClick()然后跳转到startActivity(intent)时,它会失败。

堆栈跟踪:

java.lang.NullPointerException: null
    at android.app.Activity.startActivityFromFragment(Activity.java:3850)
    at android.app.Activity.startActivityFromFragment(Activity.java:3825)
    at android.app.Fragment.startActivity(Fragment.java:996)
    at android.app.Fragment.startActivity(Fragment.java:975)
    at com.********.android.***project*****.controller.HomeScreenFragment$1.onClick(HomeScreenFragment.java:42)
    at android.view.View.performClick(View.java:4084)
    at com.*********.android.***project***.HomeScreenFragmentTest.testSignInButton2(HomeScreenFragmentTest.java:83)

我知道如何使用Robolectric.buildActivity()方法启动Robolectric中的活动,但这只适用于需要进行测试的活动。为什么在代码中Robolectric无法运行startActivity()方法?是否有更好的测试方法?


这似乎是一个真正的Robolectric问题。普通的startActivity方法由ShadowContextWrapper处理,但是Fragment不像ActivityService对象一样是一个Context,因此尝试运行真正的Android代码时会出错。我将其作为问题#767提交了。 - Corey D
如果您有兴趣为Robolectric做出贡献,可以尝试fork它,编写一个测试,并创建我在问题中描述的shadow方法,然后提交pull request。您可以查看其他startActivity()方法以获得灵感。 - Corey D
1个回答

10
你还需要在你的ActivityController上调用.start().resume(),而不仅仅是调用.create()。这将导致片段也被创建。
如果你遵循上述要求,就不需要自己调用onCreateView。只需使用mHomeScreenActivity.findViewById(R.id.sign_in_button);从活动中获取按钮即可。
一般来说,我怀疑你的代码失败是因为片段还没有完全启动,因为你没有调用start()resume()

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