I am trying to write a unit test for an extended AEM core component - a 'button' with an extra field. I use the delegation pattern, and Lombok to reduce implementation code.
My unit test is failing when attempting to get the button ID (inherited from the button super-type) - with a null reference exception - because 'button' is null.
Why would that be? Have I set up my unit test incorrectly? Or could it be that I have used the delegation pattern for the core component incorrectly?
It is driving me crazy!
INTERFACE:
@ProviderType
public interface ExtendedButton extends Button {
String RESOURCE_TYPE = "myproject/components/extendedbutton";
String getVariant();
}
IMPL:
@Model(
adaptables = { Resource.class, SlingHttpServletRequest.class },
adapters = { ExtendedButton.class, Button.class, ComponentExporter.class },
resourceType = ExtendedButton.RESOURCE_TYPE,
defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL
)
@Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION)
public class ExtendedButtonImpl implements ExtendedButton {
@Delegate
@Self
@Via(type = ResourceSuperType.class)
private Button button;
@ValueMapValue
@Getter
private String variant;
// EXAMPLE
// without lombok, the getter for button ID would be;
public String getId() {
return (null != button) ? button.getId() : null;
}
}
UNIT TEST CODE:
@ExtendWith(AemContextExtension.class)
class ExtendedButtonModelTest {
private final AemContext context = new AemContextBuilder()
.plugin(CORE_COMPONENTS)
.build();
private ExtendedButton model;
@BeforeEach
public void setup() {
context.create().resource("/apps/myproject/components/extendedbutton",
PROPERTY_RESOURCE_SUPER_TYPE, "core/wcm/components/button/v2/button");
Page page = context.create().page("/content/test-page");
context.currentResource(context.create().resource(page, "extendedbutton",
PROPERTY_RESOURCE_TYPE, ExtendedButton.RESOURCE_TYPE,
JCR_TITLE, "button text",
"variant", "light",
"id", "button id",
"linkURL", "https://google.com",
"linkTarget", "_blank",
"accessibilityLabel", "button label"
));
model = context.request().adaptTo(ExtendedButton.class);
}
// UNIT TEST SUCCEEDS
@Test
void testGetVariant() {
String val = model.getVariant();
assertNotNull(val);
assertEquals("light", val);
}
// UNIT TEST THROWS NULL POINTER EXCEPTION ON MODEL
@Test
void testGetButtonId() {
String val = model.getId();
assertNotNull(val);
assertEquals("button-id", val);
}
}
CodePudding user response:
Oh my! This turned out to be a very, very simple issue. In the above unit test code, I used two constants;
PROPERTY_RESOURCE_SUPER_TYPE
PROPERTY_RESOURCE_TYPE
These were incorrect - and from the wrong import library, since they were "resourceSuperType" and "resourceType" respectively - missing the "sling:" prefix!!!!!!
The correct constants, are;
import static org.apache.sling.jcr.resource.api.JcrResourceConstants.SLING_RESOURCE_SUPER_TYPE_PROPERTY;
import static org.apache.sling.jcr.resource.api.JcrResourceConstants.SLING_RESOURCE_TYPE_PROPERTY;
The fundamental line to the unit test, being;
context.create().resource("/apps/myproject/components/extendedbutton",
SLING_RESOURCE_SUPER_TYPE_PROPERTY, "core/wcm/components/button/v2/button");
which instructs the unit test which core component to extend from.