zawadz88/MaterialPopupMenu

UI Testing Robolectric Issue

JamesRoome opened this issue · 4 comments

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()
    }
}

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!

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.

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!

Yes is works, happy to delete my CustomRobolectricTestRunner!

Thanks for the quick fix.