在 espresso 测试期间,当使用保存的实例状态重新创建活动时,似乎总是抛出这个解组异常。我用一个非常基本的安卓应用程序复制了它。以下是步骤:
创建一个包含两个活动的 android 应用程序,每个活动都有一个按钮。第一个活动上的按钮打开第二个活动。第二个活动上的按钮关闭当前活动。
添加一个 espresso 测试,它只是打开第一个活动,单击按钮(打开第二个活动),然后单击第二个活动上的按钮(完成第二个活动并返回第一个活动)。
在您的模拟器上,请务必在您的模拟器上启用“不要保留活动”。
在我的真实应用程序中,它会根据活动而有所不同,哪个类将“未知”导致解组。在这个特定的例子中,它显然是工具栏。我发现通过从保存的实例状态中删除特定条目(“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)