I have some code I want to test with Robolectric. Basically I want to test that a button click launches an activity.
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
}
}
}
}
My test looks like this: HomeSreenFragmentTest.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
}
The problem I am having is with the test. The code itself works fine in emulator/on device. The problem is that when Robolectric runs the performClick()
method, and then gets to onClick()
then goes to startActivity(intent)
it fails.
Stacktrace:
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)
I know how to start an activity with Robolectric using the Robolectric.buildActivity()
method. But this is for when I need an activity in testing. Why is Robolectric failing to run the startActivity()
method in code? Is there a better way to test this?
You should also call .start().resume()
on your ActivityController
, not only .create()
This causes the fragment to be created as well.
If you do the above, you won't need to call onCreateView
yourself. You can just get the button from the activity using mHomeScreenActivity.findViewById(R.id.sign_in_button);
In general I suspect your code fails because the fragment hasn't fully started yet, because you didn't call start()
and resume()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With