Testing that button starts an Activity with Robole

2019-03-09 08:07发布

问题:

Hi I have the following code:

@RunWith(Test9Runner.class)
public class MainActivityTest 
{
    private MainActivity activity;
    private Button pressMeButton;

    @Before
    public void setUp() throws Exception 
    {
        activity = new MainActivity();
        activity.onCreate(null);
        pressMeButton = (Button) activity.findViewById(R.id.button1);
    }

    @Test
    public void shouldUpdateResultsWhenButtonIsClicked() throws Exception 
    {
        pressMeButton.performClick();
        ShadowActivity shadowActivity = shadowOf(activity);
        Intent intent = shadowActivity.getResultIntent();
        System.out.print(intent.toString());
    }
}

But I have no idea how to test that pressing pressMeButton started a new Activity. Actually it does, but how to write the correct Robolectric unit test for this fact?

回答1:

Use Robolectric's StartedMatcher

@RunWith(Test9Runner.class) 
public class MainActivityTest  {
    private MainActivity activity;
    private Button pressMeButton;

    @Before
    public void setUp() throws Exception 
    {
        activity = new MainActivity();
        activity.onCreate(null);
        pressMeButton = (Button) activity.findViewById(R.id.button1);
    }

    @Test
    public void shouldStartNextActivityWhenButtonIsClicked() 
    {
        pressMeButton.performClick();
        assertThat(activity, new StartedMatcher(NextActivity.class));
    }  
}


回答2:

In Robolectric 2.1.1 you can verify if Intent starting new Activity was emitted in following way.

@RunWith(RobolectricTestRunner.class)
public class MyTest {
  private ShadowActivity shadowActivity;
  private MyActivity activity;

  @Before
  public void setup() {
    activity = new MyActivity();
    shadowActivity = Robolectric.shadowOf(activity);        
  }

  @Test
  public shouldStartNewActivityWhenSomething() {
    //Perform activity startup
    //Do some action which starts second activity, for example View::performClick()
    //...
    //Check Intent
    Intent intent = shadowActivity.peekNextStartedActivityForResult().intent;
    assertThat(intent.getStringExtra(MySecondActivity.EXTRA_MESSAGE)).isEqualTo("blebleble");
    assertThat(intent.getComponent()).isEqualTo(new ComponentName(activity, MySecondActivity.class));
  }
}

This is similar to what I am doing. Please note that creating Activity by calling new Activity() will make Robolectric print warnings about creating activity improperly, this probably can be done better...



回答3:

Updating this for 3.1.2 as the answers above did not work for me:-

    loginButton.callOnClick();

    Intent startedIntent = shadowOf(activity).getNextStartedActivity();
    ShadowIntent shadowIntent = shadowOf(startedIntent);
    assertEquals(NextActivity.class, shadowIntent.getIntentClass()); 


回答4:

Inspired by @MichK's answer, here is a complete running test using the buildActivity method chain from Robolectric 2.2+:

@Test
public void testStartScheduleActivity() {
    HomeScreenActivity homeActivity = Robolectric.buildActivity(HomeScreenActivity.class).create().start().visible().get();
    ShadowActivity shadowHome = Robolectric.shadowOf(homeActivity);
    Button btnLaunchSchedule = (Button) homeActivity.findViewById(R.id.btnLaunchSchedule);
    Robolectric.clickOn(btnLaunchSchedule);

    assertThat(shadowHome.peekNextStartedActivityForResult().intent.getComponent(), equalTo(new ComponentName(homeActivity, ScheduleActivity.class)));
}


回答5:

This is how does it looks like for the Robolectric 3

        // Click on the image view
    mShareLocationImageView.performClick();

    // Check the startActivityForResult for ShareUserLocationActivity has been triggered
    ShadowActivity shadowActivity = Shadows.shadowOf(mChatWindowsActivity);
    Intent intent = shadowActivity.peekNextStartedActivityForResult().intent;
    assertThat(intent).hasComponent(new ComponentName(mChatWindowsActivity, ShareUserLocationActivity.class));


回答6:

@Before
public void setUp() throws Exception {
    mMainActivity = Robolectric.buildActivity(MainActivity.class)
            .create().start().visible().get();

    shadowActivity =Shadows.shadowOf(mMainActivity);
    hourlyButton = (Button) mMainActivity.findViewById(R.id.hourlyButton);
}
@Test
public void hourlyActivityButtonTest() throws Exception {

   Thread.sleep(5000);
    hourlyButton.performClick();
    Intent intent = shadowActivity.peekNextStartedActivityForResult().intent;
    assertThat(intent.getComponent()).isEqualTo(new ComponentName(mMainActivity, HourlyForecastActivity.class));

}


回答7:

Having not used any of the unit testing in android, i am not sure if this will work:

In the activity you are starting, you could make a static variable called "instance".

private static TheActivitysName instance;

In the activity onCreate you set the instance variable:

instance = this;

And then you create a static method to get this variable.

public static TheActivitysName getInstance() {
    return instance;
}

In your test, you can then test on TheActivitysName.getInstance(). If it is null, then the activity has not been started. If it is different from null, then the activity has been created.

I'm not sure if code to check will be executed before the activity has had time to been created though.