Java 在finish()之后从活动中获取结果;在Android单元测试中

Java 在finish()之后从活动中获取结果;在Android单元测试中,java,android,unit-testing,junit,android-intent,Java,Android,Unit Testing,Junit,Android Intent,我目前正在编写一些Android单元测试,虽然我已经得到了大多数我想要的工作方式,但有一件事让我有些困惑 我的测试活动中包含以下代码: Intent result = new Intent(); result.putExtra("test", testinput.getText().toString()); setResult(Activity.RESULT_OK, result); finish(); 我试图弄清楚如何使用工具(或其他工具)来读取活动的结果,或在活动完成后获得意图。 有人能帮

我目前正在编写一些Android单元测试,虽然我已经得到了大多数我想要的工作方式,但有一件事让我有些困惑

我的测试活动中包含以下代码:

Intent result = new Intent();
result.putExtra("test", testinput.getText().toString());
setResult(Activity.RESULT_OK, result);
finish();
我试图弄清楚如何使用工具(或其他工具)来读取活动的结果,或在活动完成后获得意图。
有人能帮忙吗

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

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

回到使用startActivityForResult的活动中。

您可以通过编写一个特殊的活动来实现这一点,该活动的唯一目的是启动您正在测试的活动,以获取结果,并保存结果,以便您断言正确性

例如,您可以创建一个名为
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
启动的活动,您可以通过在其
onCreate
方法中使用
getIntent
轻松实现这一点。在您的测试用例中,在调用getActivity之前调用setActivityIntent以设置用于启动活动的意图。

您可以使用反射并直接从活动中获取值

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);
  }
}
或者,您也可以使用和隐藏测试中的活动。然后,ShadowActivity为您提供了一些方法,可以轻松地知道活动是否正在完成,并检索其结果代码

例如,我的一个测试如下所示:

@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());
}

是的,类似的问题。我在问之前看到了,但是没有好的答案。用一些代码启动了一个新的方法…因为您无法更改
setResult(int)
的实现,因此必须相信它可以工作,所以只需验证该方法是否已在您当前的
活动中调用就够了吗?
是的,这是正确的,谢谢。但是,我要问的是关于单元测试用例的问题。你能给你看到的关于特定问题的问题增加一点细节吗?谢谢,我会测试这个!然而,我意识到我的问题应该是这样的:单元测试接受用户输入的活动的结果。(也就是说,活动从屏幕上获取输入。)很容易单独测试,但很难进行单元测试。我不知道所有这些是否都可以称为“单元测试”,真的…太棒了!我在单元测试中使用它而不是getActivity.getResultCode(),它工作得很好
shadowActivity.isFinishing()
现在已被弃用,
Activity
直接提供该标志,只需使用
MacActivity.isFinishing
@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());
}