Are there working examples for testbench with quarkus?

Hi there,

I’m currently evaluating vaadin as a possible UI for our quarkus application and have a hard time to get the tests working,
I could solve nearly all problems so far, but now I’m stuck with a classloading issue

java.lang.ClassNotFoundException: mytest.vaadinpoc.ReportView
    at io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:489)
    at io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:466)
    at java.base/java.lang.Class.forName0(Native Method)
    at java.base/java.lang.Class.forName(Class.java:375)
    at com.vaadin.testbench.unit.internal.Routes.autoDiscoverViews(Routes.kt:82)

For this test

@QuarkusTest
class ReportViewTest extends UIUnitTest {
    @Test
    void removemelater() {
        final ReportView reportView = navigate(ReportView.class);
    }
}

I debugged a little bit into the classloader and all project own classes are not accessible by the classloader which vaadin currently uses. Since all other tests are working I tend to believe there is more than one classloader doing its work under the hood, but I don’t have any knowledge about how quarkus works there. So, I’m not sure if there is something I am missing or if it is a fundamental problem.

Are there any working, up-to-date examples for vaadin with quarkus and tests?

Env:
Quarkus 3.0.2
Vaadin 24.+
JDK 17 (corretto)

Ok, further down the rabbit hole:

@JvmOverloads
    fun autoDiscoverViews(vararg packageNames: String? = arrayOf()): Routes = apply {
        val classGraph: ClassGraph = ClassGraph().enableClassInfo()
                .enableAnnotationInfo()
                .acceptPackages(*(packageNames.map { it ?: "" }.toTypedArray()))
        classGraph.scan().use { scanResult: ScanResult ->
            scanResult.getClassesWithAnnotation(Route::class.java.name).mapTo(routes) { info: ClassInfo ->
                Class.forName(info.name).asSubclass(Component::class.java) <-- !!! breaks here
            }
            scanResult.getClassesImplementing(HasErrorParameter::class.java.name).mapTo(errorRoutes) { info: ClassInfo ->
                Class.forName(info.name).asSubclass(HasErrorParameter::class.java)
            }
        }

        cleanupErrorRoutes()

        println("Auto-discovered views: $this")
    }

Class.forName won’t be able to find project classes. It looks like the extensions are loaded with a different classloader which isolates the extensions.
ClassLoader.getSystemClassLoader().loadClass("mytest.vaadinpoc.ReportView") this however works.

Does ReportView inject some service classes?

Yes, but the same will happen with classes which look like this

@Route(value = "", layout = MainLayout.class)
@PageTitle("Default")
@Unremovable
public class DefaultView extends HorizontalLayout {
    public DefaultView() {
        add(new H1("Default View"));
    }
}

Based on my debugging, the classloader used to load the vaadin extension does not have access to the project files, while the systemClassLoader works.

Is that a test view or an application view?

You shouldn’t access the application code in TestBench tests, as you’re testing the browser, not the Java code.

Oh, right, you’re using UI Unit Testing, that’s a different case.

Hi, yes. I actually wanted to try out the testing capabilities but got stuck with the class loading issue.
I did a cross post on the quarkus github (https://github.com/quarkusio/quarkus/discussions/33240), to check if they have some insights why this behaves like it does.

As mentioned above, changing the lines in Vaadins autoDiscoverViews from Class.forName(...) to ClassLoader.getSystemClassLoader().loadClass(...) does the trick. But I’m not aware of the possible side effects. And can’t be done from my side :slightly_smiling_face:

If I had to guess, you’re probably the first one trying that particular combo of tools

Sad to hear. Should I open a bug ticket in github for the quarkus-extension? I’ve opened a bug ticket for this https://github.com/vaadin/quarkus/issues/121

:+1:

Just to keep this thread updated.

The issue was closed and replaced by one on the testbench project: https://github.com/vaadin/testbench/issues/1655
Furthermore we created a working starter project: https://github.com/AliceAndTheBuilders/pro-starter-flow-quarkus