Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI Testing Robolectric Issue #73

Closed
JamesRoome opened this issue Nov 11, 2020 · 4 comments
Closed

UI Testing Robolectric Issue #73

JamesRoome opened this issue Nov 11, 2020 · 4 comments
Assignees
Labels
Milestone

Comments

@JamesRoome
Copy link

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
Copy link
Owner

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!

@zawadz88 zawadz88 self-assigned this Nov 12, 2020
@JamesRoome
Copy link
Author

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 zawadz88 added this to the 4.1.0 milestone Nov 21, 2020
@zawadz88 zawadz88 added the bug label Nov 21, 2020
zawadz88 pushed a commit that referenced this issue Nov 21, 2020
When running Robolectric tests we would get the following error:
`java.lang.IllegalAccessError: tried to access class kotlin.jvm.internal.DefaultConstructorMarker from class androidx.appcompat.widget.MaterialRecyclerViewPopupWindow$Companion`.

Additional changes:
- changed visibility of some internal classes i.e. `MaterialRecyclerViewPopupWindow` & `SectionedRecyclerViewAdapter` as they were not meant to be exposed anyway
- update Gradle & AGP versions
- target API version 28 -> 29
- moved `SanityTest` to `sharedTest` source set so that it can be tested with Robolectric as well
@zawadz88 zawadz88 mentioned this issue Nov 21, 2020
zawadz88 pushed a commit that referenced this issue Nov 21, 2020
When running Robolectric tests we would get the following error:
`java.lang.IllegalAccessError: tried to access class kotlin.jvm.internal.DefaultConstructorMarker from class androidx.appcompat.widget.MaterialRecyclerViewPopupWindow$Companion`.

Additional changes:
- changed visibility of some internal classes i.e. `MaterialRecyclerViewPopupWindow` & `SectionedRecyclerViewAdapter` as they were not meant to be exposed anyway
- update Gradle & AGP versions
- target API version 28 -> 29
- moved `SanityTest` to `sharedTest` source set so that it can be tested with Robolectric as well
@zawadz88
Copy link
Owner

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
Copy link
Author

Yes is works, happy to delete my CustomRobolectricTestRunner!

Thanks for the quick fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants