Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 活动生命周期单元测试_Android_Unit Testing - Fatal编程技术网

Android 活动生命周期单元测试

Android 活动生命周期单元测试,android,unit-testing,Android,Unit Testing,在活动单元测试中,如何模拟活动生命周期事件 我可以调用仪器的callActivityOn。。。方法,但如何触发活动重新创建,以便活动的OnCreate获得已保存状态的捆绑包如果您有Android 4.x设备,则可以进入“设置”>“开发人员选项”并选中“不保留活动”。现在,每当您的活动失去焦点时(例如:HOME按钮),它将被终止,并调用onSaveInstanceState(…) 恢复应用程序时,如果将活动保存在onSaveInstanceState(…)中,那么它应该在onCreate(…)方法

在活动单元测试中,如何模拟活动生命周期事件


我可以调用仪器的callActivityOn。。。方法,但如何触发活动重新创建,以便活动的OnCreate获得已保存状态的捆绑包如果您有Android 4.x设备,则可以进入“设置”>“开发人员选项”并选中“不保留活动”。现在,每当您的活动失去焦点时(例如:HOME按钮),它将被终止,并调用onSaveInstanceState(…)


恢复应用程序时,如果将活动保存在onSaveInstanceState(…)中,那么它应该在onCreate(…)方法中包含捆绑数据。

官方开发指南中有一个非常好的示例,介绍了状态管理测试。基本上,您只需要调用Activity.finish()来模拟活动已终止,请查看下面的伪代码:

public void testIfStateIsSaved() {
  // Open myActivity first time.
  MyActivity myActivity = getActivity();
  final EditText editText = (EditText) myActivity.findViewById(com.company.R.id.edit_text);
  // emulate some user action
  myActivity.runOnUiThread(new Runnable() {
    public void run() {
      editText.setText("save me");
    }
  });

  // Suppose you have implemented saved state properly.

  // kill activity and restart it again.
  myActivity.finish();
  myActivity = getActivity();
  final EditText editText2 = (EditText) myActivity.findViewById(com.company.R.id.edit_text);
  assertEquals("user input must be saved", "save me", editText2.getText());
}
希望这有帮助。

不要遵循:{死链接}

myActivity.finish();
myActivity = getActivity();
ActivityInstrumentationTestCase2.getActivity()
在您第一次调用该活动时启动该活动,但在测试用例中的每个后续调用中,它都会简单地返回相同的活动。因此,您仍在查看已完成的活动

完成第一个活动后,您需要从测试开始一个新的活动。例如,您可以使用
InstrumentationTestCase.launchActivity()

作为另一个例子,我编写了一个测试,按下ActivityA中的一个按钮,启动ActivityB获取结果;然后,测试立即终止ActivityA(通过方向更改,但finish()也可以),然后测试获得系统在ActivityB完成时创建的新ActivityA的句柄并发送其结果。其中的诀窍是让测试添加Instrumentation.ActivityMonitor,然后让该监视器等待系统启动新的ActivityA并给测试一个句柄

编辑2012年2月23日cdhabecker,添加可复制代码:

public class VerboseActivity extends Activity {
    public final static String TAG = "Verbose";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.i(TAG, "onCreate() " + (Activity)this);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity5);
    }
    @Override
    protected void onDestroy() {
        Log.i(TAG, "onDestroy().");
        super.onDestroy();
    }
}
测试用例:(sleep()调用为活动提供了大量的响应时间)


请注意,
finish()
导致了
onDestroy()
,但随后的
getActivity()
是不可操作的。getActivity()不仅没有实例化新活动,甚至没有重新创建原始活动。

我发现此代码导致创建新活动:

myActivity.finish();
setActivity(null);
myActivity = getActivity();
但这不会导致调用onSaveInstanceState。例如,为了测试活动是否在视图方向更改后正确创建,该测试应执行以下操作:

private mInstrumentation = getInstrumentation();
...
final Bundle outState = new Bundle();
mInstrumentation.callActivityOnSaveInstanceState(mActivity, outState);
mActivity.finish();
setActivity(null);
mActivity = getActivity();
runTestOnUiThread(new Thread() {
    @Override
    public void run() {
        mInstrumentation.callActivityOnRestoreInstanceState(mActivity, outState);
    }
});

我确认
cdhabecker
是正确的,getActivity()返回在开始时创建的活动,即使您“完成”了它。但我想我已经找到了一个测试活动娱乐性的方法。您可以尝试请求更改方向。这将重新创建活动,然后检索新创建的活动。下面的代码片段:(我用过):


当然,如果你阻止你的活动在方向改变后被破坏,它将不起作用。您可以找到包含日志消息的完整答案。希望有帮助。问候

在详细阐述cdhabecker的答案后,我创建了以下适合我的静态方法:

public static Activity restartActivity(Activity activity, Instrumentation instrumentation, Intent intent){
    String className = activity.getClass().getName();
    Instrumentation.ActivityMonitor monitor = instrumentation.addMonitor(className, null, false);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.setClassName(instrumentation.getTargetContext(), className );
    instrumentation.startActivitySync(intent);
    Activity newActivity = instrumentation.waitForMonitor(monitor);
    instrumentation.removeMonitor(monitor);
    return newActivity;
}
使用活动后,我会销毁它并通过调用

activity.finish();
setActivity(null);

在my ActivityInstrumentationTestCase2类中。

您可以通过
ActivityLifeCycleMonitor

例如,此方法等待并将新创建的
活动设置为当前活动

public void waitAndSetResumedActivity() {
    // well at least there are some activities in the pipeline - lets see if they resume.

    long[] waitTimes =
            {10, 50, 100, 500, TimeUnit.SECONDS.toMillis(2), TimeUnit.SECONDS.toMillis(30)};

    final ActivityLifecycleMonitor activityLifecycleMonitor = ActivityLifecycleMonitorRegistry.getInstance();
    final AtomicBoolean activityResumed = new AtomicBoolean(false);
    for (int waitIdx = 0; waitIdx < waitTimes.length; waitIdx++) {
        if (activityResumed.get()) return;
        try {
            Thread.sleep(waitTimes[waitIdx]);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        getInstrumentation().runOnMainSync(new Runnable() {
            @Override
            public void run() {
                Collection<Activity> resumedActivities = activityLifecycleMonitor.getActivitiesInStage(Stage.RESUMED);
                if (!resumedActivities.isEmpty()) {
                    activity = (MainActivity) resumedActivities.iterator().next();
                    setActivity(activity);
                    activityResumed.set(true);
                }
            }
        });

    }
    throw new NoActivityResumedException("No activities in stage RESUMED. Did you forget to "
            + "launch the activity. (test.getActivity() or similar)?");

}

这可能适用于手动测试。我正在寻找一种在自动测试中实现这一点的方法。我认为这个答案行不通——你会发现getActivity()根本没有启动新的活动——它和你以前的一样。请参阅,了解另一种方法。我最初认为这是答案,但后来证明我错了-请参阅@cdhabecker的注释。您可以提供可靠的参考来支持您的陈述“它只是在测试用例中的每个后续调用中返回相同的活动”吗?顺便说一句,我认为这里的关键点是调用Activity.finish(),它将完全破坏具有用户输入状态的活动,我回答中的测试代码用于检查Activity.onCreate()中是否正确实现了相同的实例(我根据您的语句假设,尽管状态不同)返回。@yorkw我添加了一个可复制的大小写。我仍然不明白为什么
Thread。sleep(5000L)
导致在
finish()之后调用onStop()>ondestory()。sleep()技巧对我很有效,因为我希望调用onStop()和onDestroy()。
public static Activity restartActivity(Activity activity, Instrumentation instrumentation, Intent intent){
    String className = activity.getClass().getName();
    Instrumentation.ActivityMonitor monitor = instrumentation.addMonitor(className, null, false);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.setClassName(instrumentation.getTargetContext(), className );
    instrumentation.startActivitySync(intent);
    Activity newActivity = instrumentation.waitForMonitor(monitor);
    instrumentation.removeMonitor(monitor);
    return newActivity;
}
activity.finish();
setActivity(null);
public void waitAndSetResumedActivity() {
    // well at least there are some activities in the pipeline - lets see if they resume.

    long[] waitTimes =
            {10, 50, 100, 500, TimeUnit.SECONDS.toMillis(2), TimeUnit.SECONDS.toMillis(30)};

    final ActivityLifecycleMonitor activityLifecycleMonitor = ActivityLifecycleMonitorRegistry.getInstance();
    final AtomicBoolean activityResumed = new AtomicBoolean(false);
    for (int waitIdx = 0; waitIdx < waitTimes.length; waitIdx++) {
        if (activityResumed.get()) return;
        try {
            Thread.sleep(waitTimes[waitIdx]);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        getInstrumentation().runOnMainSync(new Runnable() {
            @Override
            public void run() {
                Collection<Activity> resumedActivities = activityLifecycleMonitor.getActivitiesInStage(Stage.RESUMED);
                if (!resumedActivities.isEmpty()) {
                    activity = (MainActivity) resumedActivities.iterator().next();
                    setActivity(activity);
                    activityResumed.set(true);
                }
            }
        });

    }
    throw new NoActivityResumedException("No activities in stage RESUMED. Did you forget to "
            + "launch the activity. (test.getActivity() or similar)?");

}
Activity activity = getActivity(); // old activity    
//rotate it
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
//set new Activity
waitAndSetResumedActivity();
activity = getActivity();  // New Activity