adobe / adobe/aem-core-wcm-components
[DefaultPathProcessor] Implementation-dependent tests in testVanityUrl and testVanityConfig
- Dominant language
- Java
- Stars
- 795
- Forks
- 775
- Avg merge
- 3d 22h
- Merged PRs (30d)
- 8
Description
## Bug Report
**Current Behavior**
The `DefaultPathProcessorTest#testVanityUrl` and `DefaultPathProcessorTest#testVanityConfig` methods exhibit flaky behavior when execution order is non-deterministic (e.g., when using NonDex for testing). The tests fail intermittently with different error patterns:
**testVanityUrl failures:**
org.apache.sling.testing.mock.osgi.ReferenceViolationException: Unable to inject mandatory reference 'externalizer' (com.day.cq.commons.Externalizer) for class com.adobe.cq.wcm.core.components.internal.link.DefaultPathProcessor : no matching services were found.
**testVanityConfig failures:**
org.opentest4j.AssertionFailedError: expected: but was:
org.opentest4j.AssertionFailedError: expected: but was:
**Steps to reproduce:**
1. Run NonDex on the test: `mvn edu.illinois:nondex-maven-plugin:2.1.7:nondex -Dtest=DefaultPathProcessorTest#testVanityUrl`
2. Observe intermittent failures across different seeds (e.g., fails on seeds 933178, 974622 but passes on 1016066)
**Expected behavior/code**
Tests should pass consistently regardless of execution order or service registration timing. The tests should be deterministic and not depend on implementation-specific ordering of:
- OSGi service registration and dependency injection
- Resource resolver path mapping behavior
**Environment**
- **AEM Core Components version:** 2.30.3-SNAPSHOT
- **Test framework:** JUnit 5 with AEM Mocks
- **Build tool:** Maven with NonDex plugin 2.1.7
- **JRE version:** OpenJDK 64-Bit Server VM
**Possible Solution**
**For testVanityUrl:**
```java
// Ensure Externalizer service is available before registering DefaultPathProcessor
Externalizer externalizer = context.getService(Externalizer.class);
if (externalizer == null) {
// Fallback: register a mock externalizer if not already present
externalizer = mock(Externalizer.class);
when(externalizer.publishLink(any(ResourceResolver.class), anyString()))
.thenAnswer(invocation -> "https://example.org" + invocation.getArgument(1, String.class));
context.registerService(Externalizer.class, externalizer);
}
```
**For testVanityConfig:**
- Replaced hardcoded path assertions with controlled mock `ResourceResolver` instances
- Eliminated dependency on non-deterministic path mapping behavior
- Used explicit mocking to ensure predictable test outcomes
**Additional context / Screenshots**
This issue highlights the importance of:
1. **Deterministic test design** - Tests should not rely on service registration order
2. **Proper dependency setup** - Explicitly ensure required services are available before component instantiation
3. **NonDex integration** - Regular flaky test detection in CI/CD pipelines
The flaky behavior would cause intermittent CI failures and reduce confidence in the test suite, potentially masking real regressions.
Contributor guide
Research direction
Find DefaultPathProcessorTest and start by reading testVanityUrl and testVanityConfig, then run the provided NonDex Maven command across different seeds. Trace the Externalizer setup and resource resolver path mapping used by those tests. Done means both tests pass consistently regardless of execution order or service registration timing.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- testing-qa
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100