zawadz88 / MaterialPopupMenu

Shows Material popup menus grouped in sections & more
Apache License 2.0
646 stars 57 forks source link

UI Testing Robolectric Issue #73

Closed JamesRoome closed 3 years ago

JamesRoome commented 3 years ago

Error When trying to do automated UI tests with Robolectric I get this error:

java.lang.IllegalAccessError: tried to access class kotlin.jvm.internal.DefaultConstructorMarker from class androidx.appcompat.widget.MaterialRecyclerViewPopupWindow$Companion

This is caused by MaterialRecyclerViewPopupWindow being in the androidx namespace so Robolectric does its bytecode magic on it.

Fix: Don't put MaterialRecyclerViewPopupWindow in the androidx namespace.

Workaround: Use a custom RobolectricTestRunner

 * https://github.com/robolectric/robolectric/issues/4340
 *
 * https://github.com/zawadz88/MaterialPopupMenu/blob/master/material-popup-menu/src/main/java/androidx/appcompat/widget/MaterialRecyclerViewPopupWindow.kt
 * MaterialRecyclerViewPopupWindow uses the androidx namespace, so Robolectric tries to instrument it, which doesn't turn out well.
 */
class CustomRobolectricTestRunner(testClass: Class<*>?, injector: Injector) : RobolectricTestRunner(testClass) {
    private var androidConfigurer: AndroidConfigurer = injector.getInstance(AndroidConfigurer::class.java)

    @Suppress("unused")
    constructor(testClass: Class<*>?): this(testClass, defaultInjector().build())

    override fun createClassLoaderConfig(method: FrameworkMethod?): InstrumentationConfiguration {
        val configuration: ConfigurationStrategy.Configuration = (method as RobolectricFrameworkMethod).configuration
        val config: Config = configuration.get(Config::class.java)

        val builder = Builder(super.createClassLoaderConfig(method))
        builder.doNotInstrumentClass("androidx.appcompat.widget.MaterialRecyclerViewPopupWindow\$Companion")
        androidConfigurer.configure(builder, interceptors)
        androidConfigurer.withConfig(builder, config)
        return builder.build()
    }
}
zawadz88 commented 3 years ago

Thanks for submitting this issue and a workaround! I'm not sure if I can move the package. If remember correctly it was needed to access some package-private resources. I'll have a look if this can be fixed by other means though!

JamesRoome commented 3 years ago

I didn't look into the details too much, other than "bytecode instrumentation magic". But now that I'm thinking about it, all you might need to tweak the companion object a bit so the instrumentation works.

zawadz88 commented 3 years ago

Hi @JamesRoome, This should be now fixed in 4.1.0. Thanks for reporting this and providing a lot of info to fix the issue!

JamesRoome commented 3 years ago

Yes is works, happy to delete my CustomRobolectricTestRunner!

Thanks for the quick fix.