SpringUIUnitTest Parallel Execution Issue
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 25
- Forks
- 25
- Avg merge
- 5h 9m
- Merged PRs (30d)
- 44
Description
SpringUIUnitTest Parallel Execution Issue
Summary
SpringUIUnitTest fails when test classes are executed in parallel due to bean registration conflicts in the shared Spring application context.
Environment
- Vaadin: 24.8.7
- Spring Boot: 3.5.5
- JUnit 5: 5.11.3
- Java: 21
Problem Description
When running multiple test classes that extend SpringUIUnitTest in parallel, tests fail with:
java.lang.IllegalStateException: Could not register object [com.vaadin.testbench.unit.mocks.SpringSecurityRequestCustomizer@XXX]
under bean name 'com.vaadin.testbench.unit.mocks.SpringSecurityRequestCustomizer':
there is already object [com.vaadin.testbench.unit.mocks.SpringSecurityRequestCustomizer@YYY] bound
Root Cause
The UITestSpringLookupInitializer class registers beans as singletons in the Spring context. When multiple test classes run in parallel and share the same Spring context, they attempt to register the same bean multiple times, causing conflicts.
Minimal Reproducible Example
https://github.com/Artur-/springuitest-parallel-issue
Expected Behavior
Tests should run successfully in parallel without bean registration conflicts.
Actual Behavior
Tests fail with:
java.lang.IllegalStateException: Could not register object [com.vaadin.testbench.unit.mocks.SpringSecurityRequestCustomizer@1d76957d]
under bean name 'com.vaadin.testbench.unit.mocks.SpringSecurityRequestCustomizer':
there is already object [com.vaadin.testbench.unit.mocks.SpringSecurityRequestCustomizer@27fa67ee] bound
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.addSingleton(DefaultSingletonBeanRegistry.java:162)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.addSingleton(DefaultListableBeanFactory.java:1460)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.registerSingleton(DefaultSingletonBeanRegistry.java:146)
at com.vaadin.testbench.unit.UITestSpringLookupInitializer.beforeTestMethod(UITestSpringLookupInitializer.java:56)
Analysis
The issue occurs in UITestSpringLookupInitializer.beforeTestMethod() which registers beans without checking if they already exist:
// Problematic code in UITestSpringLookupInitializer
@Override
public void beforeTestMethod(TestContext testContext) {
ConfigurableApplicationContext context = (ConfigurableApplicationContext) testContext.getApplicationContext();
ConfigurableListableBeanFactory factory = context.getBeanFactory();
// This fails when multiple threads try to register the same bean
factory.registerSingleton(SpringSecurityRequestCustomizer.class.getName(),
new SpringSecurityRequestCustomizer());
// ... other bean registrations
}
Workarounds
Workaround 1: Disable Parallel Execution
# junit-platform.properties
junit.jupiter.execution.parallel.enabled=false
Workaround 2: Use @DirtiesContext (Slow)
@SpringBootTest
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public abstract class BaseUITest extends SpringUIUnitTest {
// Each test class gets its own context, but this is very slow
}
Workaround 3: Use @Isolated Annotation
@Isolated // Forces sequential execution for this test class
public class CriticalUITest extends BaseUITest {
// Tests run sequentially
}
Suggested Fix
The UITestSpringLookupInitializer should check if beans are already registered before attempting to register them:
@Override
public void beforeTestMethod(TestContext testContext) {
ConfigurableApplicationContext context = (ConfigurableApplicationContext) testContext.getApplicationContext();
ConfigurableListableBeanFactory factory = context.getBeanFactory();
String beanName = SpringSecurityRequestCustomizer.class.getName();
// Check if bean is already registered
if (!factory.containsSingleton(beanName)) {
synchronized (factory) {
// Double-check inside synchronized block
if (!factory.containsSingleton(beanName)) {
factory.registerSingleton(beanName, new SpringSecurityRequestCustomizer());
}
}
}
// ... similar pattern for other beans
}
Or alternatively, use prototype scope or unique bean names per test:
String beanName = SpringSecurityRequestCustomizer.class.getName() + "_" + testContext.getTestClass().getName();
factory.registerSingleton(beanName, new SpringSecurityRequestCustomizer());
Impact
- Performance: Forces users to run tests sequentially, significantly increasing test execution time
- CI/CD: Longer build times in continuous integration pipelines
- Developer Experience: Slower feedback loop during development
- Scalability: Cannot leverage multi-core processors for test execution
Additional Notes
- This issue affects all projects using SpringUIUnitTest with parallel test execution
- The problem becomes more pronounced as the test suite grows
- Modern CI environments encourage parallel execution for faster builds
References
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with UITestSpringLookupInitializer.beforeTestMethod() and the linked minimal reproduction, then run the tests with JUnit parallel execution enabled to observe the singleton registration conflict. Trace the other bean registrations in this initializer and verify that the test suite completes in parallel without duplicate-bean failures.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, spring-boot
- Domain
- backend, testing-qa
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 45/100