Instrumental Testing with FragmentScenario

后端 未结 3 2158
伪装坚强ぢ
伪装坚强ぢ 2021-02-14 21:27

I\'m trying to use the new FragmentScenario APIs of the androidx testing libraries for local testing and instrumentation testing(androidTest). The api works fine in local enviro

3条回答
  •  梦如初夏
    2021-02-14 21:56

    In my case the activity that the fragment is launched in, EmptyFragmentScenario, could not be opened because of a

    Caused by: java.lang.ClassNotFoundException: Didn't find class androidx.fragment.app.testing.FragmentScenario$EmptyFragmentActivity
    

    See the full stacktrace:

    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
    

    I couldn't find the correct dependency I need in order for that EmptyFragmentActivity to be included at runtime so my temporary workaround was to not use launchFragmentInContainer and instead launch my own Activity:

    My test activity:

    class TestFragmentActivity : AppCompatActivity() {
      override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
      }
    
      fun replaceFragment(fragment: Fragment) {
        supportFragmentManager
            .beginTransaction()
            .replace(android.R.id.content, fragment)
            .commit()
      }
    }
    

    My test:

    @RunWith(AndroidJUnit4::class)
    class MyFragmentAndroidTest {
    
      @get:Rule val activityRule: ActivityTestRule =
          ActivityTestRule(TestFragmentActivity::class.java)
    
      @Test
      fun test() {
        activityRule.activity.replaceFragment(MyFragment.newInstance())
    
        onView(withId(R.id.title)).check(matches(withText("Title"))))
        // More assertions.
      }
    }
    

提交回复
热议问题