JUnit Test Cases for Sling Models based on Delegation Pattern | Community
Skip to main content
New Participant
December 24, 2019
Solved

JUnit Test Cases for Sling Models based on Delegation Pattern

  • December 24, 2019
  • 12 replies
  • 28399 views

I am trying to write jUnit test cases for custom teaser component which extends the core Teaser component using the Delegation Pattern for Sling Models using "@Self @2434638(type=ResourceSuperType.class)" as specified here: https://github.com/adobe/aem-core-wcm-components/wiki/Delegation-Pattern-for-Sling-Models
When I try to set the context (io.wcm.testing.mock.aem.junit5.AemContext) and adapt the context's request (I've tried resource as well) to the model I have created (like the "PageHeadline" from the example), I am getting a NullPointerException.

I am using AEM 6.5.2.0 and trying to run test cases in JUnit 5

Best answer by Rick_Holdsworth

I've managed to find a solution.

 

Basically instead of relying on injection during the Unit test I've used Mockito and FieldSetter.setField

 

The only change to the source code would be to ensure the defaultInjectionStrategy was Optional. Not ideal but minimal

 

First we need to adapt the request to core Teaser.class

Teaser coreTeaser = request.adaptTo(Teaser.class);

Then we adapt the request to our custom teaser

CustomTeaser underTest = request.adaptTo(CustomTeaser.class);

Then we set the field that's not injecting

try {
FieldSetter.setField(underTest, underTest.getClass().getDeclaredField("teaser"), coreTeaser);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}

 

Specific to Teaser I also had to set some SlingBindings so that @ScriptVariables were set when adapting the request to Teaser.class

@BeforeEach

request = context.request();

Component component = mock(Component.class);
Style style = mock(Style.class);
SlingBindings slingBindings = (SlingBindings) request.getAttribute(SlingBindings.class.getName());
slingBindings.put(WCMBindingsConstants.NAME_COMPONENT, component);
slingBindings.put(WCMBindingsConstants.NAME_CURRENT_STYLE, style);
request.setAttribute(SlingBindings.class.getName(), slingBindings);

 

Following may only be specific to our POM setup but thought I'd add for completeness 

 

I also had to bump aem mock junit5 dependency to

<artifactId>io.wcm.testing.aem-mock.junit5</artifactId>
<version>4.0.0</version>

 

12 replies

joerghoh
Employee
December 27, 2019

have you registered the Sling model for the core teaser component as well to the context?

 

Jörg

New Participant
January 2, 2020
Yes. I have included it in the context as follows: context.addModelsForClasses(com.adobe.cq.wcm.core.components.models.Teaser.class);
arunpatidar
New Participant
December 24, 2019

Hi,

You need to use one more adaptable to adapt Teaser Component 

e.g.

@Model(adaptables = SlingHttpServletRequest.class, adapters = {Teaser.class, CustomTeaser.class}, resourceType = TeaserImpl.RESOURCE_TYPE)

 

Use CustomeTaeser to adapt to Junit test cases.

 

It will not cover 100% coverage but you will be able to write test cases for custom functionality.

Arun Patidar
New Participant
December 27, 2019
I tried adding that additional adapter class and I'm still getting null when I try to adapt the context request to my CustomTeaser