0

在 espresso 测试期间,当使用保存的实例状态重新创建活动时,似乎总是抛出这个解组异常。我用一个非常基本的安卓应用程序复制了它。以下是步骤:

  1. 创建一个包含两个活动的 android 应用程序,每个活动都有一个按钮。第一个活动上的按钮打开第二个活动。第二个活动上的按钮关闭当前活动。

  2. 添加一个 espresso 测试,它只是打开第一个活动,单击按钮(打开第二个活动),然后单击第二个活动上的按钮(完成第二个活动并返回第一个活动)。

  3. 在您的模拟器上,请务必在您的模拟器上启用“不要保留活动”。

在我的真实应用程序中,它会根据活动而有所不同,哪个类将“未知”导致解组。在这个特定的例子中,它显然是工具栏。我发现通过从保存的实例状态中删除特定条目(“androidx.lifecycle.BundlableSavedStateRegistry.key”和“android:viewHierarchyState”),它将在浓缩咖啡测试期间解决此异常,但当然不会恢复正确。我会重申,这只是运行 espresso 测试时的问题。当手动执行完全相同的测试步骤时,一切都会正确解组并且没有例外。

更改 sdk 版本似乎也无济于事。

而已。

这是所有血淋淋的代码:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
//        // This will cause the exception to not be thrown during espresso tests
//        if(savedInstanceState != null) {
//            savedInstanceState.remove("androidx.lifecycle.BundlableSavedStateRegistry.key");
//            savedInstanceState.remove("android:viewHierarchyState");
//        }
        

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findViewById(R.id.open_button).setOnClickListener(v -> startActivity(new Intent(MainActivity.this, ChildActivity.class)));
    }
}
public class ChildActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_child);

        findViewById(R.id.close_button).setOnClickListener(v -> finish());
    }
}
@LargeTest
@RunWith(AndroidJUnit4.class)
public class MainActivityTest {

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

    @Test
    public void test() {
        onView(withId(R.id.open_button)).perform(click());
        onView(withId(R.id.close_button)).perform(click());
        onView(withId(R.id.open_button)).check(matches(isDisplayed()));
    }
}
androidx.test.espresso.PerformException: Error performing 'single click - At Coordinates: 115, 272 and precision: 16, 16' on view 'view.getId() is <2131231192/com.example.myapplication:id/close_button>'.
    at androidx.test.espresso.PerformException$Builder.build(PerformException.java:1)
    at androidx.test.espresso.base.PerformExceptionHandler.handleSafely(PerformExceptionHandler.java:8)
    at androidx.test.espresso.base.PerformExceptionHandler.handleSafely(PerformExceptionHandler.java:9)
    at androidx.test.espresso.base.DefaultFailureHandler$TypedFailureHandler.handle(DefaultFailureHandler.java:4)
    at androidx.test.espresso.base.DefaultFailureHandler.handle(DefaultFailureHandler.java:5)
    at androidx.test.espresso.ViewInteraction.waitForAndHandleInteractionResults(ViewInteraction.java:8)
    at androidx.test.espresso.ViewInteraction.desugaredPerform(ViewInteraction.java:11)
    at androidx.test.espresso.ViewInteraction.perform(ViewInteraction.java:8)
    at com.example.myapplication.MainActivityTest.mainActivityTest(MainActivityTest.java:31)
    ... 32 trimmed
Caused by: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: androidx.appcompat.widget.Toolbar$SavedState
    at android.os.Parcel.readParcelableCreator(Parcel.java:2839)
    at android.os.Parcel.readParcelable(Parcel.java:2765)
    at android.os.Parcel.readValue(Parcel.java:2668)
    at android.os.Parcel.readSparseArrayInternal(Parcel.java:3118)
    at android.os.Parcel.readSparseArray(Parcel.java:2351)
    at android.os.Parcel.readValue(Parcel.java:2725)
    at android.os.Parcel.readArrayMapInternal(Parcel.java:3037)
    at android.os.BaseBundle.initializeFromParcelLocked(BaseBundle.java:288)
    at android.os.BaseBundle.unparcel(BaseBundle.java:232)
    at android.os.Bundle.getSparseParcelableArray(Bundle.java:1010)
    at com.android.internal.policy.PhoneWindow.restoreHierarchyState(PhoneWindow.java:2133)
    at android.app.Activity.onRestoreInstanceState(Activity.java:1135)
    at android.app.Activity.performRestoreInstanceState(Activity.java:1090)
    at android.app.Instrumentation.callActivityOnRestoreInstanceState(Instrumentation.java:1317)
    at android.app.ActivityThread.handleStartActivity(ActivityThread.java:2953)
    at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:180)
    at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:165)
    at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:142)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at androidx.test.espresso.base.Interrogator.loopAndInterrogate(Interrogator.java:14)
    at androidx.test.espresso.base.UiControllerImpl.loopUntil(UiControllerImpl.java:8)
    at androidx.test.espresso.base.UiControllerImpl.loopUntil(UiControllerImpl.java:1)
    at androidx.test.espresso.base.UiControllerImpl.injectMotionEvent(UiControllerImpl.java:6)
    at androidx.test.espresso.action.MotionEvents.sendUp(MotionEvents.java:7)
    at androidx.test.espresso.action.MotionEvents.sendUp(MotionEvents.java:1)
    at androidx.test.espresso.action.Tap.sendSingleTap(Tap.java:5)
    at androidx.test.espresso.action.Tap.sendSingleTap$bridge(Unknown Source:0)
    at androidx.test.espresso.action.Tap$1.sendTap(Tap.java:3)
    at androidx.test.espresso.action.GeneralClickAction.perform(GeneralClickAction.java:6)
    at androidx.test.espresso.ViewInteraction$SingleExecutionViewAction.perform(ViewInteraction.java:2)
    at androidx.test.espresso.ViewInteraction.doPerform(ViewInteraction.java:25)
    at androidx.test.espresso.ViewInteraction.doPerform$bridge(Unknown Source:0)
    at androidx.test.espresso.ViewInteraction$1.call(ViewInteraction.java:2)
    at androidx.test.espresso.ViewInteraction$1.call(ViewInteraction.java:1)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at android.os.Handler.handleCallback(Handler.java:873)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:193)
    at android.app.ActivityThread.main(ActivityThread.java:6669)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
4

1 回答 1

0

据我所知,您应该改用ActivityScenario,然后使用ActivityScenario.moveToStateActivityScenario.recreate测试不同活动的状态。

于 2021-11-02T19:09:50.020 回答