Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/345.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
Java 使用instrumentation和JUnit4测试重新创建Android活动_Java_Android_Automated Tests_Instrumentation_Android Junit - Fatal编程技术网

Java 使用instrumentation和JUnit4测试重新创建Android活动

Java 使用instrumentation和JUnit4测试重新创建Android活动,java,android,automated-tests,instrumentation,android-junit,Java,Android,Automated Tests,Instrumentation,Android Junit,我想为重新创建活动编写测试。执行旋转是可选的 我希望测试是用谷歌“祝福”的测试框架的最新版本编写的。我不熟悉编写测试,所以我想学习基本的、主流的、支持良好的工具。只要我掌握了基本知识,任何第三方测试框架都可以。既然我想测试非常基本的,经常发生的场景,基本的工具就足够了,对吗 最小测试代码: public class MainActivity extends AppCompatActivity { static int creationCounter = 0; Integer i

我想为重新创建活动编写测试。执行旋转是可选的

我希望测试是用谷歌“祝福”的测试框架的最新版本编写的。我不熟悉编写测试,所以我想学习基本的、主流的、支持良好的工具。只要我掌握了基本知识,任何第三方测试框架都可以。既然我想测试非常基本的,经常发生的场景,基本的工具就足够了,对吗

最小测试代码:

public class MainActivity extends AppCompatActivity {

    static int creationCounter = 0;
    Integer instanceId;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ++creationCounter;
        instanceId = new Integer(creationCounter);
        Log.d("TEST", "creating activity " + this + ", has id " + instanceId);
    }
}
测试级别:

@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {

    @Rule
    public ActivityTestRule<MainActivity> mActivityTestRule = new ActivityTestRule<>(MainActivity.class);

    @Test
    public void useAppContext() throws Exception {

        MainActivity activity1 = mActivityTestRule.getActivity();
        int act1 = activity1.instanceId.intValue();
        int counter1 = MainActivity.creationCounter;
        assertEquals(1, counter1);
        assertEquals(1, act1);


        Log.d("TEST", "requesting rotation");
        // method 1
         activity1.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        // method 2 //https://gist.github.com/nbarraille/03e8910dc1d415ed9740#file-orientationchangeaction-java
        // onView(isRoot()).perform(orientationLandscape());

        getInstrumentation().waitForIdleSync(); // I thought this should suffice
        // How to do this?
        //somehowRefreshActivityInstanceInsideTestRule();

        MainActivity activity2 = mActivityTestRule.getActivity();
        int act2 = activity2.instanceId.intValue();
        int counter2 = MainActivity.creationCounter;
        Log.d("TEST", "newly acquired activity " + activity2 + " has id " + act2 + "/" + counter2);

        assertEquals(2, counter2);
        assertEquals(2, act2);
    }
}
但我不知道如何把它翻译成新版本

编辑:

上述两种方法都使活动处于销毁状态:assertFalse(mactivityTesture.getActivity().isDestroyed());失败了


我找到了另一个方法(),它重新创建活动实例,但不通过onSaveInstanceState保持其状态

我终于在这里找到了有效的解决方案:

在适应我的需要后,代码如下所示:

public class CurrentActivityTestRule<T extends Activity> extends ActivityTestRule<T> {
    public CurrentActivityTestRule(Class<T> activityClass) {
        super(activityClass, false);
    }

    public CurrentActivityTestRule(Class<T> activityClass, boolean initialTouchMode) {
        super(activityClass, initialTouchMode, true);
    }

    public CurrentActivityTestRule(Class<T> activityClass, boolean initialTouchMode, boolean launchActivity) {
        super(activityClass, initialTouchMode, launchActivity);
    }

    public T getCurrentActivity() {
        getInstrumentation().waitForIdleSync();
        final Activity[] activity = new Activity[1];
        getInstrumentation().runOnMainSync(new Runnable() {
            @Override
            public void run() {
                java.util.Collection<Activity> activities = ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(Stage.RESUMED);
                activity[0] = Iterables.getOnlyElement(activities);
            }});
        T current = (T) activity[0];
        return current;
    }
}
onView(isRoot()).perform(orientationLandscape());
Activity oldActivityInstance = mActivityTestRule.getActivity();
Activity currentActivityInstance = mActivityTestRule.getCurrentActivity();
我在使用库版本时遇到了以下问题:

androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
    exclude group: 'com.android.support', module: 'support-annotations'
})
androidTestCompile('com.android.support.test:runner:0.5', {
    exclude group: 'com.android.support', module: 'support-annotations'
})

当前版本的
android.test.rule
解决了这个问题。
在调用
activityTestRule.getActivity()
@MateuszL的解决方案现在仍然可以与androidx测试编排器和Kotlin一起使用,以防此版本对任何人都有帮助:

import androidx.test.espresso.core.internal.deps.guava.collect.Iterables
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
import androidx.test.rule.ActivityTestRule
import androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry
import androidx.test.runner.lifecycle.Stage

class CurrentActivityTestRule<T : Activity> : ActivityTestRule<T> {

    val currentActivity: T
        get() {
            getInstrumentation().waitForIdleSync()
            val activity = arrayOfNulls<Activity>(1)
            getInstrumentation().runOnMainSync(Runnable {
                val activities = ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(Stage.RESUMED)
                activity[0] = Iterables.getOnlyElement(activities)
            })
            @Suppress("UNCHECKED_CAST")
            return activity[0] as T
        }

    constructor(activityClass: Class<T>) : super(activityClass, false)

    constructor(activityClass: Class<T>, initialTouchMode: Boolean) : super(activityClass, initialTouchMode, true)

    constructor(activityClass: Class<T>, initialTouchMode: Boolean, launchActivity: Boolean) : super(
        activityClass,
        initialTouchMode,
        launchActivity
    )
}

ActivityTestRule.getActivity不会创建新的活动,只是为您提供相同的实例。我知道这不起作用。我想知道如何使其工作,而不一定使用ActivityTestRule这仍然适用于androidx和androidx测试编排器,以及Kotlin。添加答案以防对任何人都有帮助,并引用您的答案作为来源。
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
    exclude group: 'com.android.support', module: 'support-annotations'
})
androidTestCompile('com.android.support.test:runner:0.5', {
    exclude group: 'com.android.support', module: 'support-annotations'
})
import androidx.test.espresso.core.internal.deps.guava.collect.Iterables
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
import androidx.test.rule.ActivityTestRule
import androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry
import androidx.test.runner.lifecycle.Stage

class CurrentActivityTestRule<T : Activity> : ActivityTestRule<T> {

    val currentActivity: T
        get() {
            getInstrumentation().waitForIdleSync()
            val activity = arrayOfNulls<Activity>(1)
            getInstrumentation().runOnMainSync(Runnable {
                val activities = ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(Stage.RESUMED)
                activity[0] = Iterables.getOnlyElement(activities)
            })
            @Suppress("UNCHECKED_CAST")
            return activity[0] as T
        }

    constructor(activityClass: Class<T>) : super(activityClass, false)

    constructor(activityClass: Class<T>, initialTouchMode: Boolean) : super(activityClass, initialTouchMode, true)

    constructor(activityClass: Class<T>, initialTouchMode: Boolean, launchActivity: Boolean) : super(
        activityClass,
        initialTouchMode,
        launchActivity
    )
}
@Suppress("CAST_NEVER_SUCCEEDS")
private fun getRegistrationActivity()= activityTestRule.currentActivity as RegistrationActivity