Docs

Test Configuration

Set Vaadin application properties, feature flags, and Lookup services for a single test class or test method.

@BrowserlessTestConfig declares Vaadin application properties, feature flags, and Lookup services for the standard browserless environment. Each configuration belongs to the environment created for its test and is discarded with that environment. This is Vaadin test configuration, not a replacement for Spring, Quarkus, or CDI bean configuration.

The custom CDI initialization in this documentation calls MockVaadin.setup() directly and does not pass a BrowserlessConfiguration to it. Adding the annotation alone to that custom setup does not apply these settings.

For a step-by-step example, see Configure a Browserless Test.

Settings

Attribute Description

applicationProperties

name=value pairs applied to the Vaadin deployment configuration, such as "devmode.sessionSerialization.enabled=true". The value is everything after the first =, so a value can itself contain =. The properties are set before the servlet starts, so code that runs at startup, such as a VaadinServiceInitListener, already sees them.

featureFlags

Either a feature identifier, to enable the feature, or an id=true|false pair. These flags override the feature flag sources that apply outside a test — the vaadin-featureflags.properties file and the vaadin.experimental.* system properties. Toggling a flag this way needs no development mode and writes nothing into the project folder. An unknown identifier fails with an error that lists the available flags.

lookupServices

Implementation classes registered with the Vaadin Lookup, such as an InstantiatorFactory or a ResourceProvider.

The browserless application property itself stays enforced and cannot be overridden.

Merging Class and Method Configuration

Every annotation a test inherits contributes to the configuration, rather than being shadowed by the nearest one. The merge works entry by entry: a property name or feature identifier declared in more than one place takes the value of the highest-ranking declaration, while the names declared only once all apply. The closer a declaration is to the test method, the higher it ranks: the method first, then the test class, then superclasses from the nearest up, and then, for a @Nested test, enclosing classes from the innermost out. A method-level feature setting replaces the class-level value for that identifier without removing unrelated application properties.

Source code
Java
@BrowserlessTestConfig(applicationProperties = "base.property=fromBase")
abstract class AbstractViewTest extends BrowserlessTest {
}

@BrowserlessTestConfig(featureFlags = "defaultAutoResponsiveFormLayout")
class CartViewTest extends AbstractViewTest {
    // Both base.property and defaultAutoResponsiveFormLayout apply
}

Lookup services are the exception to the ranking: they have no name to resolve, so every declared service is registered. A test method can add a service, but cannot remove one that its test class declares. The services that the Spring and Quarkus integrations need are always registered, and the test configuration never affects them.

A method-level annotation needs an environment built for each test method. When one environment is shared by the whole class, as with BrowserlessClassExtension, the annotation is rejected with an error naming the methods that carry it. Move it to the test class in that case.

Configuring without Annotations

The same settings can be built in code. On a JUnit 6 extension:

Source code
Java
@RegisterExtension
BrowserlessExtension extension = new BrowserlessExtension()
        .withApplicationProperty("devmode.sessionSerialization.enabled", "true")
        .withFeatureFlags("defaultAutoResponsiveFormLayout");

On the application context builder of a multi-user test:

Source code
Java
try (var app = BrowserlessApplicationContext.create(builder -> builder
        .withViewPackages(CartView.class)
        .withFeatureFlags("defaultAutoResponsiveFormLayout"))) {
    // ...
}

A BrowserlessApplicationContext is created in plain code rather than by a JUnit extension, so it never looks at @BrowserlessTestConfig: only what its own builder declares applies. To reuse the configuration declared by a test class, pass it explicitly with BrowserlessConfiguration.from(…​):

Source code
Java
try (var app = BrowserlessApplicationContext.create(builder -> builder
        .withViewPackages(CartView.class)
        .withConfiguration(BrowserlessConfiguration.from(getClass())))) {
    // ...
}

from(…​) reads a single annotation — the one declared on the given class, or the one inherited from its nearest annotated superclass — rather than merging the whole hierarchy the way an extension does.

Or by overriding testConfiguration() on a test that extends a base class:

Source code
Java
@Override
protected BrowserlessConfiguration testConfiguration() {
    return BrowserlessConfiguration.builder()
            .withConfiguration(super.testConfiguration())
            .withFeatureFlags("defaultAutoResponsiveFormLayout")
            .build();
}

On an extension, a configuration built in code wins over the class-level annotation, and loses against the method-level one. A testConfiguration() override ranks differently: super.testConfiguration() returns the configuration already resolved from the annotations, so whatever the override adds on top of it wins over all of them, the method-level annotation included. Build on super.testConfiguration() to refine the declared configuration, and leave out the values that a test method needs to override.

Note
Spring Properties Win
With Spring, a Vaadin property defined in the Spring environment, such as vaadin.devmode.sessionSerialization.enabled in application.properties, is applied by SpringServlet on top of the test configuration, and therefore wins over @BrowserlessTestConfig. Use @TestPropertySource to override such a property for a test. Properties that are not Vaadin init parameters are unaffected.

CD70CAA5-6506-4810-BED5-0F54DCE2F0FA

Updated