Let's say you have one activity which displays the user's name, and a second activity which asks the user for their name:
class NameShowingActivity extends Activity { private static final int NAME_RESPONSE = 1; TextView nameView; @Override protected void onCreate(Bundle savedInstanceState) { nameView = new TextView(this); } void askForUserName() { startActivityForResult( new Intent(this, NameChooserActivity.class), NAME_RESPONSE); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == NAME_RESPONSE) { if (resultCode == RESULT_OK) { nameView.setText(data.getStringExtra("name")); } else if (resultCode == RESULT_CANCELED) { nameView.setText("No name given."); } } } }
Let's test it! The askForName() method launches our name chooser activity, which will eventually respond with the entered name. We want to ensure that the name view has been updated with that name:
@RunWith(RobolectricTestRunner.class) public class NameShowingActivityTest { private NameShowingActivity nameShowingActivity; @Before public void setUp() throws Exception { nameShowingActivity = new NameShowingActivity(); nameShowingActivity.onCreate(null); } @Test public void shouldFillNameViewFromChooserResponse() throws Exception { nameShowingActivity.askForUserName(); shadowOf(nameShowingActivity).receiveResult( new Intent(nameShowingActivity, NameChooserActivity.class), Activity.RESULT_OK, new Intent().putExtra("name", "Joe")); assertEquals("Joe", nameShowingActivity.nameView.getText()); } }
When you call receiveResult() on your activity's shadow, Robolectric notices that the activity is listening for a response from the NameChooserActivity, so it passes the result intent (the second one) to your activity's onActivityResult() method.
But we're not testing the RESULT_CANCELLED branch of our code. Let's test that too:
public void shouldDisplayErrorMessageInNameViewWhenUserCancels() throws Exception { nameShowingActivity.askForUserName(); shadowOf(nameShowingActivity).receiveResult( new Intent(nameShowingActivity, NameChooserActivity.class), Activity.RESULT_CANCELED, null); assertEquals("No name given.", nameShowingActivity.nameView.getText()); }
Thank you for this post, very helpful!
ReplyDeleteJust some note for those who get the following error:
java.lang.RuntimeException: No intent matches Intent{componentName=ComponentName{pkg='ru.alvik.cafe', cls='ru.alvik.cafe.PaymentActivity'}} among []
at com.xtremelabs.robolectric.shadows.ShadowActivity.receiveResult(ShadowActivity.java:365)
at ru.alvik.cafe.CafeActivityTest.testClearOrderAfterPaymentCompleted(CafeActivityTest.java:79)
You have probably just started the activity rather than starting it for result.
Hello I am facing this error while calling the startActivityForResult(intent, 0)
ReplyDeletejava.lang.RuntimeException: No intent matches Intent{componentName=ComponentName{pkg='com.android.test', cls='com.android.CaptureActivity'}, extras=null} among [Intent{componentName=ComponentName{pkg='com.android.test', cls='com.android.CaptureActivity'}, extras=null}]
Here is how I am calling:
Intent intent = new Intent(ActivityDetail.this, CaptureActivity.class);
intent.putExtra("FromScreen", 1);
intent.putExtra("BUTTON_CLICK_STATE",false);
startActivityForResult(intent, 0);
Please , let me know what I am doing wrong
Thanks