【问题标题】:Get result from an activity after finish(); in an Android unit test在完成()之后从活动中获取结果;在 Android 单元测试中
【发布时间】:2011-07-31 00:02:21
【问题描述】:

我目前正在编写一些 Android 单元测试,虽然我已经让大多数事情按照我想要的方式工作,但有一件事让我有点难过。

我在测试中的活动中有以下代码:

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

我正在尝试弄清楚如何使用 Instrumentation(或其他)来读取活动的结果,或者在活动完成后获得意图。 任何人都可以帮忙吗?

【问题讨论】:

  • 是的,类似的问题。问之前看到了,但没有好的答案。用一些代码开始了一个新的......
  • 由于您无法更改 setResult(int) 的实现,因此必须相信它可以正常工作,因此仅验证该方法是否在您当前的 Activity? 中被调用还不够吗跨度>

标签: java android unit-testing junit android-intent


【解决方案1】:

或者您也可以使用 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());
}

【讨论】:

  • shadowActivity.isFinishing() 现在已弃用,Activity 直接提供该标志,只需使用 mActivity.isFinishing
【解决方案2】:

您可以使用反射并直接从 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's   private fields for mResultCode or mResultData.  Time to update the reflection code.", e);
  } catch (Exception e) {
    throw new RuntimeException(e);
  }
}

【讨论】:

  • 太棒了!我在单元测试中使用它而不是 getActivity.getResultCode(),这很完美
【解决方案3】:

您可以通过编写一个特殊的活动来做到这一点,其唯一目的是启动您正在测试结果的活动并保存结果以供您断言正确性。

例如,您可以创建一个名为ResultReceiverActivity 的活动。给它三个方法:getResultCodegetResultDatagetReceivedRequestCode,可用于验证测试活动是否返回了正确的值。您将创建一个扩展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 启动的活动,您可以通过在其onCreate 方法中使用getIntent 轻松做到这一点。在您的测试用例中,在调用 getActivity 之前调用 setActivityIntent 以设置用于启动 Activity 的 Intent。

【讨论】:

  • 谢谢,我会测试一下!但是,我意识到我的问题应该是这样的:对接受用户输入的活动的结果进行单元测试。 (即,活动从屏幕获取输入。)本身测试很容易,但单元测试可能更难。不知道这一切是否可以称为“单元测试”,真的......
【解决方案4】:

我不确定单元测试是否有所不同,但您应该可以使用 onActivityResult,如下所示:StartingActivities。您只需使用 startActivityForResult(intent, requestCode) 启动 Activity,然后使用

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

返回使用 startActivityForResult 的活动。

【讨论】:

  • 是的,这是真的,谢谢。但是,我是在专门询问单元测试用例。
  • 您能否在有关您所看到的具体问题的问题中添加更多细节?
猜你喜欢
  • 1970-01-01
  • 2018-05-06
  • 1970-01-01
  • 2021-09-23
  • 2023-01-04
  • 2015-01-08
  • 2019-07-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多