Получить результат активности после финиша(); в Android unit test

В настоящее время я пишу некоторые тесты для Android, и, хотя я получил большинство вещей, чтобы работать так, как я хочу, одна вещь оставила меня в тупике.

У меня есть следующий код в тестируемой моей деятельности:

Intent result = new Intent();
result.putExtra("test", testinput.getText().toString());
setResult(Activity.RESULT_OK, result);
finish();

Я пытаюсь выяснить, как использовать Instrumentation (или что-то еще), чтобы иметь возможность прочитать результат активности или получить намерение после завершения операции. Может ли кто-нибудь помочь?

Ответы

Ответ 1

Вы можете использовать отражение и захватывать значения непосредственно из Activity.

protected Intent assertFinishCalledWithResult(int resultCode) {
  assertThat(isFinishCalled(), is(true));
  try {
    Field f = Activity.class.getDeclaredField("mResultCode");
    f.setAccessible(true);
    int actualResultCode = (Integer)f.get(getActivity());
    assertThat(actualResultCode, is(resultCode));
    f = Activity.class.getDeclaredField("mResultData");
    f.setAccessible(true);
    return (Intent)f.get(getActivity());
  } catch (NoSuchFieldException e) {
    throw new RuntimeException("Looks like the Android Activity class has changed it   private fields for mResultCode or mResultData.  Time to update the reflection code.", e);
  } catch (Exception e) {
    throw new RuntimeException(e);
  }
}

Ответ 2

Или вы также можете использовать Robolectric и затенять тестируемую активность. Затем ShadowActivity предоставляет вам методы, позволяющие легко узнать, завершает ли Activity и извлекает ли ее код результата.

В качестве примера один из моих тестов выглядит следующим образом:

@Test
public void testPressingFinishButtonFinishesActivity() {
    mActivity.onCreate(null);
    ShadowActivity shadowActivity = Robolectric.shadowOf(mActivity);

    Button finishButton = (Button) mActivity.findViewById(R.id.finish_button);
    finishButton.performClick();

    assertEquals(DummyActivity.RESULT_CUSTOM, shadowActivity.getResultCode());
    assertTrue(shadowActivity.isFinishing());
}

Ответ 3

Вы можете сделать это, написав специальную деятельность, единственной целью которой является запуск активности, которую вы тестируете для результата, и сохранение результата для подтверждения правильности.

Например, вы можете создать операцию с именем ResultReceiverActivity. Дайте ему три метода: getResultCode, getResultData и getReceivedRequestCode, которые могут использоваться для проверки того, что проверенная активность вернула правильные значения. Вы создадите тестовый пример, который расширяет ActivityInstrumentationTestCase2, а общий параметр будет ResultReceiverActivity. Вызов getActivity даст вам экземпляр действия.

public class ReturnedResultTest 
    extends ActivityInstrumentationTestCase2<ResultReceiverActivity> {

    public void testReturnedResult() {
        ResultReceiverActivity a = getActivity();
        assertEquals(Activity.RESULT_OK, a.getResultCode());
        assertEquals("myResult", a.getResultData().getStringExtra("test"));
        assertEquals(0x9999, a.getReceivedRequestCode());
    }
}

ResultReceiverActivity необходимо переопределить onActivityResult, конечно, и просто сохранить значения этого параметра метода в своих полях, например:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    this.receivedRequestCode = requestCode;
    this.resultCode = resultCode;
    this.resultData = data;
}

Конечно, вы можете настроить активность, начинающуюся с ResultReceiverActivity, и вы можете легко сделать это, используя getIntent в своем методе onCreate. В тестовом случае вызовите setActivityIntent перед вызовом getActivity, чтобы установить, какой Intent используется для запуска активности.

Ответ 4

Я не уверен, что для модульных тестов это отличается, но вы должны иметь возможность использовать onActivityResult, как показано здесь: StartingActivities, Вы только начинаете действие с помощью startActivityForResult (намерение, requestCode), а затем используете

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)

обратно в действие, которое использовало startActivityForResult.