FragmentScenario configuration - Binary XML file line, Error inflating class <widget> while testing with espresso

Mat*_*Pag 4 android android-fragments android-espresso

Inflating error while trying to use FragmentScenario with launchFragment and launchFragmentInContainer if using material component in XML.

android.view.InflateException: Binary XML file line #41: Binary XML file line #41: Error inflating class <widget class>
Caused by: android.view.InflateException: Binary XML file line #41: Error inflating class <widget class>
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:334)
at android.view.LayoutInflater.createView(LayoutInflater.java:647)
at com.android.internal.policy.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:58)
at android.view.LayoutInflater.onCreateView(LayoutInflater.java:720)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:788)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:730)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:863)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
at android.view.LayoutInflater.inflate(LayoutInflater.java:515)
at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
...
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:886)
at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManagerImpl.java:1227)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:1293)
at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:710)
at androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManagerImpl.java:2063)
at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManagerImpl.java:1853)
at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1808)
at androidx.fragment.app.FragmentManagerImpl.execSingleAction(FragmentManagerImpl.java:1685)
at androidx.fragment.app.BackStackRecord.commitNow(BackStackRecord.java:554)
at androidx.fragment.app.testing.FragmentScenario$1.perform(FragmentScenario.java:308)
at androidx.fragment.app.testing.FragmentScenario$1.perform(FragmentScenario.java:286)
at androidx.test.core.app.ActivityScenario.lambda$onActivity$1$ActivityScenario(ActivityScenario.java:534)
at androidx.test.core.app.ActivityScenario$$Lambda$0.run(Unknown Source:4)
at android.app.Instrumentation$SyncRunnable.run(Instrumentation.java:2093)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Caused by: java.lang.UnsupportedOperationException: Failed to resolve attribute at index 5: TypedValue{t=0x2/d=0x7f03009f a=-1}
at android.content.res.TypedArray.getColorStateList(TypedArray.java:538)
at android.widget.TextView.<init>(TextView.java:1214)
at android.widget.Button.<init>(Button.java:166)
at android.widget.Button.<init>(Button.java:141)
at android.widget.Button.<init>(Button.java:117)
Run Code Online (Sandbox Code Playgroud)

Can't inflate XML because there are missing styles.

Mat*_*Pag 13

First of all be sure to have the latest fragment-testing dependency:

debugImplementation "androidx.fragment:fragment-testing:1.1.0-alpha05"
Run Code Online (Sandbox Code Playgroud)

Some additional info:

  1. The fix has been published in version 1.1.0-alpha03, so prior versions will not work as described here.
  2. Remember to use debugImplementation or the dependency will not work correctly, thanks to this so answer
  3. If you have errors like "process crashed, "No tests found."" check if this issue can help.

After this you can create Fragments with:

val bundle = Bundle()
.... 
launchFragmentInContainer(bundle, R.style.Theme_AppCompat) {
    YourFragment()
}
//proceed here with espresso testing
Run Code Online (Sandbox Code Playgroud)

Don't forget R.style.Theme_AppCompat otherwise Espresso will crash with the android.view.InflateException error if you use widgets coming from the com.google.android.material:material artifact. Obviously if you need a custom style you can add a new rule to your styles.xml and reference it here.

就我而言,我已配置了Navigation组件,因此我必须遵循此处官方文档的建议,以确保navController在生命周期中正常运行。

首先,我在TestFragmentUtils.kt中创建了一个通用方法

inline fun <reified F : Fragment> launchFragmentScenario(
    bundle: Bundle?, fragment: F, navController: NavController): FragmentScenario<F> {
    return launchFragmentInContainer(bundle, R.style.Theme_AppCompat) {
        fragment.also { fragment ->
            fragment.viewLifecycleOwnerLiveData.observeForever { lifeCycleOwner ->
                if (lifeCycleOwner != null) {
                    // The fragment’s view has just been created
                    Navigation.setViewNavController(fragment.requireView(), navController)
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在我YourFragmentTest我可以创建另一个方法,如:

private fun launchMyFragmentScenario(bundle: Bundle?): FragmentScenario<MyFragment> 
    //viewModel factory can be easily injected if you use FragmentFactory
    = TestFragmentUtils.launchFragmentScenario(bundle, MyFragment(viewModelFactory), navController)
Run Code Online (Sandbox Code Playgroud)

并在每次测试开始之前调用它。(navController在@Before方法中模拟了参数)

  • 是的,您应该为此评论赢得数千名声誉 (3认同)