Android 具有碎片场景的仪器测试
我正在尝试将androidx测试库的新片段场景API用于本地测试和仪器测试(androidTest)。api在本地环境中运行良好,但在仪器测试中,它会产生错误: java.lang.AssertionError:Activity从不成为请求状态“[已恢复,已销毁]”(last lifecycle transition=“PRE_ON_CREATE”)“ 帮助我进行仪器测试(androidTest) 请检查完整的错误详细信息:Android 具有碎片场景的仪器测试,android,android-testing,Android,Android Testing,我正在尝试将androidx测试库的新片段场景API用于本地测试和仪器测试(androidTest)。api在本地环境中运行良好,但在仪器测试中,它会产生错误: java.lang.AssertionError:Activity从不成为请求状态“[已恢复,已销毁]”(last lifecycle transition=“PRE_ON_CREATE”)“ 帮助我进行仪器测试(androidTest) 请检查完整的错误详细信息: java.lang.AssertionError: Activity
java.lang.AssertionError: Activity never becomes requested state "[RESUMED, DESTROYED]" (last lifecycle transition = "PRE_ON_CREATE")
at androidx.test.core.app.ActivityScenario.waitForActivityToBecomeAnyOf(ActivityScenario.java:228)
at androidx.test.core.app.ActivityScenario.launch(ActivityScenario.java:198)
at androidx.fragment.app.testing.FragmentScenario.internalLaunch(FragmentScenario.java:169)
at androidx.fragment.app.testing.FragmentScenario.launchInContainer(FragmentScenario.java:160)
at com.techzis.avatr.LoginFragmentTest1.dummyTest(LoginFragmentTest1.kt:26)
at java.lang.reflect.Method.invoke(Native Method)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at androidx.test.ext.junit.runners.AndroidJUnit4.run(AndroidJUnit4.java:104)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:388)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2152)
仪器测试(androidTest)代码为:
我认为ActivityScenario的
启动(Intent startActivityIntent)
方法有一个限制。它只希望活动恢复或销毁,如果不在4.5秒内,则抛出该错误
在活动场景的public static ActivityScenario launch(Intent startactivitycontent)
中,检查逻辑Scenario.waitForActivityToBecomeAnyOf(State.resume,State.destromed);
编辑此问题已得到修复。在我的案例中,启动片段的活动EmptyFragmentScenario无法打开,因为
Caused by: java.lang.ClassNotFoundException: Didn't find class androidx.fragment.app.testing.FragmentScenario$EmptyFragmentActivity
请参阅完整的堆栈跟踪:
2018-12-12 02:12:46.529 32659-32659/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: app.debug.test, PID: 32659
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{app.debug.test/androidx.fragment.app.testing.FragmentScenario$EmptyFragmentActivity}: java.lang.ClassNotFoundException: Didn't find class "androidx.fragment.app.testing.FragmentScenario$EmptyFragmentActivity" on path: DexPathList[[zip file "/system/framework/android.test.mock.jar", zip file "/system/framework/android.test.runner.jar", zip file "/data/app/app.debug.test-HdSyMEsvYzlt1aceQIeIuw==/base.apk"],nativeLibraryDirectories=[/data/app/app.test-HdSyMEsvYzlt1aceQIeIuw==/lib/arm64, /system/lib64, /vendor/lib64]]
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2843)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
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)
Caused by: java.lang.ClassNotFoundException: Didn't find class "androidx.fragment.app.testing.FragmentScenario$EmptyFragmentActivity" on path: DexPathList[[zip file "/system/framework/android.test.mock.jar", zip file "/system/framework/android.test.runner.jar", zip file "/data/app/app.debug.test-HdSyMEsvYzlt1aceQIeIuw==/base.apk"],nativeLibraryDirectories=[/data/app/app.debug.test-HdSyMEsvYzlt1aceQIeIuw==/lib/arm64, /system/lib64, /vendor/lib64]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:134)
at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
at android.app.AppComponentFactory.instantiateActivity(AppComponentFactory.java:69)
at android.app.Instrumentation.newActivity(Instrumentation.java:1215)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2831)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
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)
Suppressed: java.lang.NoClassDefFoundError: Failed resolution of: Landroidx/fragment/app/FragmentActivity;
at java.lang.VMClassLoader.findLoadedClass(Native Method)
at java.lang.ClassLoader.findLoadedClass(ClassLoader.java:738)
at java.lang.ClassLoader.loadClass(ClassLoader.java:363)
... 15 more
Caused by: java.lang.ClassNotFoundException: Didn't find class "androidx.fragment.app.FragmentActivity" on path: DexPathList[[zip file "/system/framework/android.test.mock.jar", zip file "/system/framework/android.test.runner.jar", zip file "/data/app/app.debug.test-HdSyMEsvYzlt1aceQIeIuw==/base.apk"],nativeLibraryDirectories=[/data/app/app.debug.test-HdSyMEsvYzlt1aceQIeIuw==/lib/arm64, /system/lib64, /vendor/lib64]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:134)
at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
... 18 more
我找不到在运行时包含EmptyFragmentActivity所需的正确依赖项,因此我的临时解决方法是不使用launchFragmentInContainer
,而是启动我自己的活动:
我的测试活动:
class TestFragmentActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
fun replaceFragment(fragment: Fragment) {
supportFragmentManager
.beginTransaction()
.replace(android.R.id.content, fragment)
.commit()
}
}
我的测试:
@RunWith(AndroidJUnit4::class)
class MyFragmentAndroidTest {
@get:Rule val activityRule: ActivityTestRule<TestFragmentActivity> =
ActivityTestRule(TestFragmentActivity::class.java)
@Test
fun test() {
activityRule.activity.replaceFragment(MyFragment.newInstance())
onView(withId(R.id.title)).check(matches(withText("Title"))))
// More assertions.
}
}
@RunWith(AndroidJUnit4::class)
类MyFragmentAndroidTest{
@get:Rule val activityRule:ActivityTestRule=
ActivityTestRule(TestFragmentActivity::class.java)
@试验
趣味测试(){
activityRule.activity.replaceFragment(MyFragment.newInstance())
onView(带id(R.id.title))。检查(匹配(带文本(“title”)))
//更多的断言。
}
}
您需要将“片段测试”依赖项添加到正在测试的APK,而不是测试APK
因此,请将build.gradle更新为
debugImplementation "androidx.fragment:fragment-testing:$fragment_version"
从
(这是由于FragmentScenario的实现细节。“FragmentTesting”声明活动,并由FragmentScenario使用。在测试APK中声明的活动在与测试中的APK不同的流程中运行。为了在同一流程中执行fragment的代码,您需要将“FragmentTesting”库放在您的APK中,而不是放在测试APK中。)
这里还有一个开发者网站。可能重复/相似之处你找到过解决方案吗?@JorgeGil
ActivityScenario
替换片段场景
?没有,但错误与ActivityScenario有关。它们不同,一个不能替换另一个。如果我没有replaceFragment()
在我的活动中?有趣的解决方法,但在我的例子中,它表示RuntimeException:无法解析以下活动的活动:Intent{act=android.Intent.action.MAIN flg=0x14000000 cmp=x.x.x.x/x.x.x.x.x.x.TestFragmentActivity}
对于未来的用户,更新我的gradle以符合此答案可能会导致我的所有测试实现返回“测试运行失败:由于“进程崩溃”而导致检测运行失败”。我建议在更新gradle后,确保此更新没有破坏所有测试。
class TestFragmentActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
fun replaceFragment(fragment: Fragment) {
supportFragmentManager
.beginTransaction()
.replace(android.R.id.content, fragment)
.commit()
}
}
@RunWith(AndroidJUnit4::class)
class MyFragmentAndroidTest {
@get:Rule val activityRule: ActivityTestRule<TestFragmentActivity> =
ActivityTestRule(TestFragmentActivity::class.java)
@Test
fun test() {
activityRule.activity.replaceFragment(MyFragment.newInstance())
onView(withId(R.id.title)).check(matches(withText("Title"))))
// More assertions.
}
}
debugImplementation "androidx.fragment:fragment-testing:$fragment_version"
androidTestImplementation "androidx.fragment:fragment-testing:$fragment_version"