Expand my Community achievements bar.

Testing Components that Extend Core Component via Sling Delegation Pattern

Avatar

Level 2

Hello All, 

 

I am using AEM as a cloud service and am using the AEM specific cloud jar file for my local instances. I am trying to test a component which uses the Sling Delegation Pattern for adding new functionality to an AEM core component. 

 

My model looks something like this:

 

@Model(adaptables = SlingHttpServletRequest.class, adapters = {List.class}, resourceType = TeaserListModel.TEASER_LIST_RESOURCE_TYPE,defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class TeaserListModel implements List {
@Self
@Via(type = ResourceSuperType.class)
private List list; // Expect V1 of ListImpl from core components to be injected here
}


My test looks like this:

public class TeaserListModelTest implements List {

private static final String TEST_BASE = "/teaserlist";
private static final String CONTENT_ROOT = "/content";
private static final String CURRENT_PAGE = "/content/list";
private static final String CONTEXT_PATH = "/context";
private static final String LIST_1 = CURRENT_PAGE + "/jcr:content/root/staticListType";
private static final String LIST_2 = CURRENT_PAGE + "/jcr:content/root/staticWithVanityPaths";

public final AemContext context = CoreComponentTestContext.newAemContext();

@BeforeEach
public void setUp() {
context.load().json(TEST_BASE + CoreComponentTestContext.TEST_CONTENT_JSON, CONTENT_ROOT);
}

@Test
void testTeaserListModelValues() {
Resource currentResource = context.currentResource("/content/list/jcr:content/root/staticListType");
TeaserListModel model = context.request().adaptTo(TeaserListModel.class);
assertNotNull(model);
}
}

 

Here is all my test-content.json (lots of different items here since I've been trying different things)

{
"teaserlist": {
"jcr:primaryType": "nt:unstructured",
"showModificationDate": true,
"tagsMatch": "any",
"linkItems": true,
"orderBy": "originalPublishDate",
"jcr:lastModifiedBy": "admin",
"jcr:created": "Tue Jul 20 2021 16:03:08 GMT+0530",
"parentPage": "/content/tsc/en",
"sortOrder": "desc",
"maxItems": "6",
"showDescription": true,
"sling:resourceType": "mycompany/components/template/teaserlist",
"childDepth": "1",
"listFrom": "children",
"dateFormat": "yyyy-MM-dd"
},
"teaserTestPage": {
"jcr:primaryType": "cq:Page",
"jcr:content": {
"jcr:primaryType": "cq:PageContent",
"jcr:title": "JCR Title",
"teaserlist": {
"jcr:primaryType": "nt:unstructured",
"showModificationDate": "true",
"jcr:createdBy": "admin",
"tagsMatch": "any",
"linkItems": "true",
"orderBy": "originalPublishDate",
"jcr:lastModifiedBy": "admin",
"jcr:created": "Wed Jul 28 2021 09:57:54 GMT-0400",
"parentPage": "/content/teaserTestPage",
"sortOrder": "asc",
"id": "345",
"maxItems": "5",
"showDescription": "true",
"jcr:lastModified": "Thu Jul 29 2021 04:19:44 GMT-0400",
"sling:resourceType": "mycompany/components/content/teaserlist",
"sling:resourceSuperType": "core/wcm/components/list",
"childDepth": "5",
"listFrom": "children"
}
},
"list": {
"jcr:primaryType": "nt:unstructured",
"showModificationDate": "false",
"jcr:createdBy": "admin",
"tagsMatch": "any",
"linkItems": "true",
"jcr:lastModifiedBy": "admin",
"jcr:created": "Wed Jul 07 2021 14:01:33 GMT-0400",
"sortOrder": "asc",
"showDescription": "true",
"jcr:lastModified": "Sun Jul 11 2021 20:39:28 GMT-0400",
"sling:resourceType": "mycompany/components/content/list",
"childDepth": "1",
"listFrom": "children"
}
},
"list": {
"jcr:primaryType": "cq:Page",
"jcr:content": {
"jcr:primaryType": "cq:PageContent",
"jcr:title": "List Page",
"root": {
"jcr:primaryType": "nt:unstructured",
"sling:resourceType": "wcm/foundation/components/responsivegrid",
"illegalListType": {
"jcr:primaryType": "nt:unstructured",
"sling:resourceType": "core/wcm/components/list",
"listFrom": "nonExisting"
},
"staticListType": {
"jcr:primaryType": "nt:unstructured",
"sling:resourceType": "core/wcm/components/list/v2/list",
"listFrom": "static",
"showThumbnail": "true",
"linkItems": "true",
"showDescription": "true",
"showModificationDate": "true",
"pages": [
"/content/list/pages/page_1",
"/content/list/pages/page_2"
]
},
"staticWithVanityPaths": {
"jcr:primaryType": "nt:unstructured",
"sling:resourceType": "core/wcm/components/list/v2/list",
"listFrom": "static",
"showThumbnail": "true",
"linkItems": "true",
"showDescription": "true",
"showModificationDate": "true",
"orderBy": "title",
"pages": [
"/content/list/pages/page_3",
"/content/list/pages/page_4"
]
}
}
},
"pages": {
"page_1": {
"jcr:primaryType": "cq:Page",
"jcr:content": {
"jcr:primaryType": "cq:PageContent",
"jcr:title": "Page 1",
"cq:lastModified": "2016-09-23T16:12:45.000-07:00"
},
"page_1_1": {
"jcr:primaryType": "cq:Page",
"jcr:content": {
"jcr:primaryType": "cq:PageContent",
"jcr:title": "Page 1.1"
}
},
"page_1_2": {
"jcr:primaryType": "cq:Page",
"jcr:content": {
"jcr:primaryType": "cq:PageContent",
"jcr:title": "Page 1.2"
},
"page_1_2_1": {
"jcr:primaryType": "cq:Page",
"jcr:content": {
"jcr:primaryType": "cq:PageContent",
"jcr:title": "Page 1.2.1"
},
"page_1_2_1_1": {
"jcr:primaryType": "cq:Page",
"jcr:content": {
"jcr:primaryType": "cq:PageContent",
"jcr:title": "Page 1.2.1.1"
}
}
}
},
"page_1_3": {
"jcr:primaryType": "cq:Page",
"jcr:content": {
"jcr:primaryType": "cq:PageContent",
"jcr:title": "Page 1.3",
"cq:tags": [
"list:test_category/test_tag"
]
}
}
},
"page_2": {
"jcr:primaryType": "cq:Page",
"jcr:content": {
"jcr:primaryType": "cq:PageContent",
"jcr:title": "Page 2",
"cq:lastModified": "2016-09-21T16:12:45.000-07:00"
}
},
"page_3": {
"jcr:primaryType": "cq:Page",
"jcr:content": {
"jcr:primaryType": "cq:PageContent",
"jcr:title": "Page 3",
"sling:vanityPath": "/page_3.html"
}
},
"page_4": {
"jcr:primaryType": "cq:Page",
"jcr:content": {
"jcr:primaryType": "cq:PageContent",
"jcr:title": "Page 4",
"sling:vanityPath": "/4_page.html"
}
}
}
}
}


My issue is that during testing, the list property of the TeaserListModel is instead of type TeaserListModel instead of ListImpl. If I omit the sling:resourceSuperType in the resources json, then list is type null. I also cannot import of the ListImpl classes since they are hidden in the internal folder of AEM core components. What I would like is the list property of TeaserListModel to be v1 of ListImpl from core components. 

When deploying to my local instance, I do see that the list property of TeaserListModel is set to the core components v1 ListImpl. Its only during testing does it seem to not find the v1 ListImpl to inject, and instead either marks the field as null, or adapts it to the TeaserListModel. 

 

Has anyone else ran into this issue before? I am also using Junit 5 with the v3.0.2 of io-mocks. 

4 Replies

Avatar

Level 1

You test content is not properly setup. You will need to include your component definition (in /apps/...) as well as define there the sling:resourceSuperType for it.

 

For an example of how to load test content in apps, have a look at https://github.com/adobe/aem-core-wcm-components/blob/master/bundles/core/src/test/java/com/adobe/cq... and https://github.com/adobe/aem-core-wcm-components/blob/master/bundles/core/src/test/resources/progres...

Avatar

Level 1

Hello! I'm trying to do the same thing with core components Container, do you have any working example of your implementation? Thank you!!

Avatar

Level 7

I tried having /apps, /mysite jsons with actual component definitions with sling:resourceSuperType, as well in /content json sling:resourceType, sling:resourceSuperType. No success in injecting @self @Via ResourceSuperType or through adaptTo

 

If you have any successful code example, can you please provide.