Hello.
Could you please tell me how to properly adapt the Resource to the ContentFragment in the tests. Since I do, I get null all the time, but the resource content fragment is not null. And in the class for which the test is written, adaptation works correctly.
Solved! Go to Solution.
Views
Replies
Total Likes
Hello @aliaksandr_hvoz,
The issue is likely with your JSON content. In order for the AEMMock resource resolver to correctly identify the your resource as a content fragment, it must satisfy some basic elements of what a content fragment is. This is the same for any JSON-based test resource.
One thing that you maybe overlooked is the presence of the metadata child which is necessary to instantiate a ContentFragment. Here is a working example:
JSON:
{
"dam": {
"content-fragment": {
"jcr:primaryType": "dam:Asset",
"jcr:content": {
"jcr:primaryType": "dam:AssetContent",
"jcr:title": "Lorem Ipsum 1",
"contentFragment": true,
"cq:name": "lorem-ipsum-1",
"metadata": {
"jcr:primaryType": "nt:unstructured"
}
}
}
}
}
Java:
import com.adobe.cq.dam.cfm.ContentFragment;
import io.wcm.testing.mock.aem.junit5.AemContext;
import io.wcm.testing.mock.aem.junit5.AemContextExtension;
import org.apache.sling.api.resource.Resource;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@ExtendWith(AemContextExtension.class)
class ContentFragmentTest {
private final AemContext context = new AemContext();
@BeforeEach
public void setUp() throws Exception {
context.load().json("/test.json", "/content");
}
@Test
public void testSomething() {
final Resource resource = context.resourceResolver().getResource("/content/dam/content-fragment");
final ContentFragment contentFragment = resource.adaptTo(ContentFragment.class);
Assertions.assertNotNull(contentFragment);
}
}
If you add these files to your project and run the test, you will be able to adapt the /content/dam/content-fragment to a ContentFragment and therefore pass the test
However, if you then delete the metadata node from the test JSON, the test will fail:
Without seeing your JSON, I can't guarantee that this is the problem, but it seems likely
If you don't know what the minimum requirements for a test JSON resource are, I recommend:
Note: You can also see in my JSON that the dam node has no properties. That's because it's purely a structural node used to create a realistic path.
Hope that helps!
Your code seems to be correct. However, you can go through this link https://docs.adobe.com/content/help/en/experience-manager-64/developing/extending-aem/customizing-co...
Also, Could you please confirm which type of resource resolver you are using?
Are you creating resource resolver via service user? If yes, could you please verify whether the corresponding service user has the read access to the content fragment and service mapping is present in OSGI. (refer this http://www.aemcq5tutorials.com/tutorials/create-system-user-in-aem/)
Regards,
Arpit
Hello @aliaksandr_hvoz,
The issue is likely with your JSON content. In order for the AEMMock resource resolver to correctly identify the your resource as a content fragment, it must satisfy some basic elements of what a content fragment is. This is the same for any JSON-based test resource.
One thing that you maybe overlooked is the presence of the metadata child which is necessary to instantiate a ContentFragment. Here is a working example:
JSON:
{
"dam": {
"content-fragment": {
"jcr:primaryType": "dam:Asset",
"jcr:content": {
"jcr:primaryType": "dam:AssetContent",
"jcr:title": "Lorem Ipsum 1",
"contentFragment": true,
"cq:name": "lorem-ipsum-1",
"metadata": {
"jcr:primaryType": "nt:unstructured"
}
}
}
}
}
Java:
import com.adobe.cq.dam.cfm.ContentFragment;
import io.wcm.testing.mock.aem.junit5.AemContext;
import io.wcm.testing.mock.aem.junit5.AemContextExtension;
import org.apache.sling.api.resource.Resource;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@ExtendWith(AemContextExtension.class)
class ContentFragmentTest {
private final AemContext context = new AemContext();
@BeforeEach
public void setUp() throws Exception {
context.load().json("/test.json", "/content");
}
@Test
public void testSomething() {
final Resource resource = context.resourceResolver().getResource("/content/dam/content-fragment");
final ContentFragment contentFragment = resource.adaptTo(ContentFragment.class);
Assertions.assertNotNull(contentFragment);
}
}
If you add these files to your project and run the test, you will be able to adapt the /content/dam/content-fragment to a ContentFragment and therefore pass the test
However, if you then delete the metadata node from the test JSON, the test will fail:
Without seeing your JSON, I can't guarantee that this is the problem, but it seems likely
If you don't know what the minimum requirements for a test JSON resource are, I recommend:
Note: You can also see in my JSON that the dam node has no properties. That's because it's purely a structural node used to create a realistic path.
Hope that helps!
Yes, it works, but one point - it works if you use JUnit 5 (io.wcm.testing.aem-mock.junit5). I have a lot of tests on JUnit 4 and I can not migrate from JUnit 4 to JUnit 5.
@Theo_Pendle and @LokeshTripathi
I was facing the same issue and followed your suggestions mentioned, it worked for me
Thanks Theo and Lokesh.
Views
Replies
Total Likes
I have got Content Fragment mock object as mentioned by @Theo_Pendle , but I got a problem at next level.
My problem was -: I was not able to get the variations from the contefragment's mocked resource which I had set from AEM context. I was loading ContentFragment in the AEM context like this in my test class.
(1) context.load().json(getClass().getResourceAsStream(CF_JSON_PATH), CF_PATH);
I was expecting that doing above will adapt to the ContentFragment Object properly and we will get everything inside ContentFragment object when below code runs into the class.
(2) ContentFragment contentFragment = resourceResolver.getResource(CF_PATH).adaptTo(ContentFragment.class);
Loading ContentFragment via Json [as mentioned at (1)] was giving Mocked ContentFragment Object, but when we were trying to access the various getter methods on ContentFragment object they were coming null.
For example I was not able to get list of Variations into my Junit for the code
(3) Iterator<VariationDef> variationIterator = contentFragment.listAllVariations();
Above problem got resolved when I replaced this line in my Junit
context.load().json(getClass().getResourceAsStream(CF_JSON_PATH), CF_PATH);
with this piece of code
ContentFragment cf = context.create().contentFragmentStructured(CF_PATH, "main", "Hello There"); cf.createVariation("variation1", "variation1 name", "variation1 description"); cf.createVariation("variation2", "variation2 name"", "variation2 description");
So basically I am not using Json to load the Mock content fragment into my Junit. With this approach we can set variations, elements etc at Content Fragment.
Reference
https://wcm.io/testing/aem-mock/junit5/apidocs/io/wcm/testing/mock/aem/builder/ContentBuilder.html
https://stackoverflow.com/questions/53124973/mocking-aem-asset-manager-using-wcm-io
Hope it helps people if they are stuck at similar point.
Happy coding.
Views
Likes
Replies