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

47
March 20, 2019, at 00:50 AM

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)

Can't inflate XML because there are missing styles.

Answer 1

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

debugImplementation "androidx.fragment:fragment-testing:1.1.0-alpha05"

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

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.

In my case I had the Navigation component configured so I had to follow the suggestion of the official documentation here to be sure the navController is ok with the lifecycle.

First of all I have create a generic method in my 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)
                }
            }
        }
    }
}

Then in my YourFragmentTest i can create another method like:

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

and call it before each test starts. (navController param is mocked in @Before method)

READ ALSO
Mock a bluetooth device

Mock a bluetooth device

I have to mock a bluetooth device that would first pair with an Android device and then send predefined data to an Android appI have no access to source code of the app, but I managed to get bluetooth communication packets sent between devices (using...

37
How to determine if a thread from the previous session is currently running

How to determine if a thread from the previous session is currently running

My app launches an AsyncTask thread that retrieves some information from a websiteWhen the user exits the app while the thread is still running, the thread continues to run

23
Add, Use and Remove Payment Methods through Lyft API

Add, Use and Remove Payment Methods through Lyft API

We would like the ability to insert new payment methods, update existing methods, use specific payment methods and delete payment methods (or make inactive) payment methods via the Lyft API

46
Running tests on remote adb server

Running tests on remote adb server

Trying to run gradle tests on remote adb server

15