UI Unit Testing in Quarkus-based Projects
In Quarkus-based projects, views may use dependency injection to get references to service and other software components. To instantiate such views and correctly handle navigation, Vaadin needs special implementation of internal components, such as QuarkusInstantiator
. Testing with UIUnitTest
provides specialized base test classes that integrate with the Quarkus Testing Framework: QuarkusUIUnitTest
, which is only supported for JUnit 5.
Subclasses can therefore rely on all of the features offered by the Quarkus Testing Framework by being annotated with @QuarkusTest
. See Quarkus Testing documentation for additional information about Quarkus testing framework.
@QuarkusTest
class ViewTest extends QuarkusUIUnitTest {
@Test
public void setText_clickButton_notificationIsShown() {
final HelloWorldView helloView = navigate(HelloWorldView.class);
test(helloView.name).setValue("Test");
test(helloView.sayHello).click();
Notification notification = $(Notification.class).first();
Assertions.assertEquals("Hello Test", test(notification).getText());
}
}
Note
|
With @QuarkusTest annotation, the testing framework starts the application and the HTTP server — although it won’t be required for UI unit testing. However, QuarkusUIUnitTest tests are still executed in a mocked environment.
|
A test can be annotated with @TestProfile
to reference a specific test configuration. With a test profile you can, for example, override application configuration, provide bean alternatives and custom test resources. Refer to the Quarkus Testing Profiles documentation for additional information.
public class MockServiceProfile implements QuarkusTestProfile {
@Override
public Map<String, String> getConfigOverrides() {
return Collections.singletonMap("app.some.config","value");
}
@Override
public Set<Class<?>> getEnabledAlternatives() {
return Collections.singleton(MockService.class);
}
}
@QuarkusTest
@TestProfile(MockServiceProfile.class)
class ViewTest extends QuarkusUIUnitTest {
}
Additional Setup
In addition to the TestBench dependency, be sure to add the Quarkus UI Unit Testing and the Quarkus test dependencies to your project. Add the following to your pom.xml
file:
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-testbench-unit-quarkus</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
Set Up View Access Control
To apply view access control, Vaadin requires a NavigationAccessControl
to be registered as a BeforeEnterListener
for the UI. Currently, the Vaadin Quarkus add-on doesn’t support automatic registration of the access control feature. To enable it for UI Unit Testing, perform the setup in a QuarkusTestProfile
class by providing an observer for the Vaadin ServiceInitEvent
that executes this step.
public class TestViewSecurityConfig implements QuarkusTestProfile {
@Override
public String getConfigProfile() {
return "test-security"; // (1)
}
@IfBuildProfile("test-security") // (1)
public static class NavigationAccessControlInitializer {
public void serviceInit(@Observes ServiceInitEvent event) { // (2)
// @QuarkusTest starts the whole application, so we check
// the VaadinService type to enable access control only for
// UI Unit tests
if (event.getSource() instanceof MockQuarkusServletService) { // (3)
event.getSource().addUIInitListener(uiEvent -> {
// Customize the NavigationAccessControl as needed
NavigationAccessControl accessControl = new NavigationAccessControl();
accessControl.setLoginView(LoginView.class);
uiEvent.getUI().addBeforeEnterListener(accessControl);
});
}
}
}
}
-
Sets the configuration profile to be used for the test. The class is annotated with
@IfBuildProfile
to make the observer only run it for tests that require this profile. -
Listens for Vaadin
ServiceInitEvent
. This is the same as implementingVaadinServiceInitListener
and registering the class to be loaded by JavaServiceLoader
. -
Checks that execution is started by the UI Unit Test. This is required because
@QuarksTest
causes the whole application to start when running the test.
NavigationAccessControl
was introduced in Vaadin 24.3. In a project based on an earlier version, view security can be configured in the same way, but using the ViewAccessChecker
component:
public class TestViewSecurityConfig implements QuarkusTestProfile {
@Override
public String getConfigProfile() {
return "test-security";
}
@IfBuildProfile("test-security")
public static class NavigationAccessControlInitializer {
public void serviceInit(@Observes ServiceInitEvent event) {
// @QuarkusTest starts the whole application, so we check
// the VaadinService type to enable access control only
// for UI Unit tests
if (event.getSource() instanceof MockQuarkusServletService) {
event.getSource().addUIInitListener(uiEvent -> {
ViewAccessChecker viewAccessChecker = new ViewAccessChecker();
viewAccessChecker.setLoginView(LoginView.class);
uiEvent.getUI().addBeforeEnterListener(viewAccessChecker);
});
}
}
}
}
Quarkus Test Security Features
When using QuarkusUIUnitTest
, if Quarkus Security is present on the classpath, the mock environment is instructed to fetch authentication details from Quarkus SecurityIdentity
.
With this support, you can use Quarkus @TestSecurity
annotation to simulate different authentication scenarios with test method granularity. More information is available from the Quarkus Security Testing documentation. Authentication details are available before creating the UI instance and navigating to the default route. Redirects to the login view aren’t performed when simulating logged-in users. In the same way, custom redirect logic for authenticated users works as expected.
To use Quarkus Security test annotations, first ensure the dependency is added to the project:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-test-security</artifactId>
<scope>test</scope>
</dependency>
Next, extend QuarkusUIUnitTest
and annotate test methods to set up an authentication scenario. For the simplest situations, use @TestSecurity
, providing the username and roles that should be granted.
@QuarkusTest
@TestProfile(TestViewSecurityConfig.class) // (1)
class ViewSecurityTest extends QuarkusUIUnitTest {
@Test
@TestSecurity(authorizationEnabled = false) // (2)
void anonymousUser_protectedView_redirectToLogin() {
navigate("protected", LoginView.class);
}
@Test
@TestSecurity(authorizationEnabled = false) // (2)
void anonymousUser_publicView_signInLinkPresent() {
// public view is default page
Assertions.assertInstanceOf(PublicView.class, getCurrentView());
Anchor anchor = $(Anchor.class).withText("Sign in").first();
Assertions.assertTrue(
test(anchor).isUsable(),
"Sign in link should be available for anonymous user");
}
@Test
@TestSecurity(user = "admin", roles = "ADMIN") // (2)
void adminUser_adminView_viewShown() {
navigate(AdminRoleView.class);
Assertions.assertTrue(
$(Avatar.class).first().isVisible(),
"Avatar should be visible for logged users");
}
}
-
Sets a profile to activate Vaadin access control feature.
-
Uses Quarkus test security annotations.
61B2F8E5-448E-4C36-82E3-D492712ECE67