JUnit 6 Extensions
Extending BrowserlessTest is the most compact way to write browserless tests, but it requires your test class to use inheritance for the Vaadin setup. When a project already has its own test base class, or you prefer composition over inheritance, the BrowserlessExtension and BrowserlessClassExtension JUnit 6 extensions provide the same functionality without requiring a specific superclass.
|
Note
|
These extensions are part of the browserless-test-junit6 artifact. They don’t replace SpringBrowserlessTest or QuarkusBrowserlessTest — for Spring and Quarkus projects, continue to extend those base classes.
|
When to Use an Extension
Use an extension when any of the following applies:
-
The test class already extends another base class that can’t be changed.
-
The project standardizes on composition-based JUnit 6 extensions.
Per-Method Lifecycle
BrowserlessExtension creates a fresh Vaadin environment before each test method and tears it down after. Register it as an instance field with @RegisterExtension:
Source code
Java
@ViewPackages(classes = CartView.class)
class CartViewTest {
@RegisterExtension
BrowserlessExtension ext = new BrowserlessExtension();
@Test
void addItemToCart() {
CartView view = ext.navigate(CartView.class);
ext.test(view.getAddButton()).click();
Assertions.assertEquals(1, view.getCartSize());
}
}Navigation, queries, and tester interactions are available as methods on the extension instance — ext.navigate(), ext.find(), ext.findInView(), ext.test(), ext.getCurrentView(), ext.fireShortcut(), ext.roundTrip(), and ext.runPendingSignalsTasks().
Per-Class Lifecycle
BrowserlessClassExtension initializes the Vaadin environment once in @BeforeAll and shares it across all tests in the class. Register it as a static field:
Source code
Java
@ViewPackages(classes = CartView.class)
class CartViewSharedTest {
@RegisterExtension
static BrowserlessClassExtension ext = new BrowserlessClassExtension();
@BeforeAll
static void setup() {
ext.navigate(CartView.class);
}
@Test
void addItem() {
// same UI instance as removeItem
ext.test(ext.find(Button.class).withText("Add").single()).click();
}
@Test
void removeItem() {
// state from addItem is preserved
}
}The same trade-offs as per-class lifecycle with BrowserlessTest apply: state leaks between tests, so write tests that tolerate leftover state or reset it explicitly.
Configuring the Extension
Both extensions support a builder-style API for configuration, used as an alternative or in addition to annotations.
| Method | Description |
|---|---|
| Adds the packages of the given classes to the route scan. Equivalent to |
| Adds package names (as strings) to the route scan. Equivalent to |
| Registers custom implementations with the Vaadin |
| Adds packages to scan for custom |
The @ViewPackages annotation still works when placed on the test class; programmatic configuration adds to what the annotation declares.
Source code
Extension with Programmatic Configuration
class AdminViewTest {
@RegisterExtension
BrowserlessExtension ext = new BrowserlessExtension()
.withViewPackages("com.example.views", "com.example.admin")
.withServices(CustomInstantiatorFactory.class)
.withComponentTesterPackages("com.example.testers");
@Test
void adminDashboardLoads() {
AdminDashboardView view = ext.navigate(AdminDashboardView.class);
Assertions.assertNotNull(view);
}
}B51F9D4A-2E73-4B18-8C6F-9A3D7E2B1C04