AEM Assets Workflow Junits | Community
Skip to main content
April 23, 2024
Solved

AEM Assets Workflow Junits

  • April 23, 2024
  • 3 replies
  • 2456 views

Hello,
I have a test workflow written in aem where i need to get the Asset

where the java test case is written as:

 

 
import javax.jcr.RepositoryException;
import org.apache.sling.api.resource.Resource;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

 
//import com.day.cq.dam.api.Asset;  //if i am using this import then its working fine
import com.adobe.granite.asset.api.Asset;  //but i want for this import
import com.adobe.granite.workflow.WorkflowException;

import io.wcm.testing.mock.aem.junit5.*;

@ExtendWith({ AemContextExtension.class, MockitoExtension.class })
class ExampleTest
{
    AemContext aemContext = new AemContext();

    @Mock
    Resource resource;

    @BeforeEach
    void setup() throws Exception
    {
        aemContext.load().json("com/example/test.json", "/content/dam");
    }

    @Test
    void testExecute() throws WorkflowException, RepositoryException {
        String resourcePath = "/content/dam/test";
        resource = aemContext.resourceResolver().getResource(resourcePath);
        System.out.println(resource.getPath()); // Output: resource path: /content/dam/test
        Asset asset = resource.adaptTo(Asset.class);
        System.out.println(asset.getPath()); // Output: asset path: null 
    }

}

JsonFile

{

"test":

{

"jcr:primaryType":"dam:Asset",

"jcr:createdBy":"admin"

}

}

 

please help me solve from above code on how to get the asset path/object so that i can retrive asset.getPath(), asset.getName() asset.getAssetMetadata()  if required 

for now its giving the value as null
request to share the sample code


Thanks & Regards.

Best answer by EstebanBustamante

Correct. It will return null if you use the com.adobe.granite.asset.api.Asset because it is not adaptable. Why are you using that? You should use the Asset implementation from com.day.cq.dam.api.Asset.

If you really want to stick with the other Asset implementation, you need to mock that class and not rely on the aemContext object. That's what I suggested as option #1 in my previous response. You should mock all of the following objects: ResourceResolver, the AdaptTo method, the AssetManager, and the Asset. The drawback with this approach is that you are not testing anything because you are setting the expected value at each step. 

** Updated Response 10/07/25 **
As pointed out by @jackki2, the implementation should not be changed to simplify writing test cases. You should prefer using com.adobe.granite.asset.api.Asset whenever possible, as it is an upper abstraction in the general AEM stack

 

 

Hope this helps

 

 

3 replies

sravs
Community Advisor
Community Advisor
April 23, 2024

Hi @vjain03 ,

 

Create an asset object using the below snippet in your Junit for the import  com.adobe.granite.asset.api.Asset.

 // to create an asset
     AssetManager assetManager = resolver.adaptTo(AssetManager.class);
     Asset newAsset = assetManager.createAsset("/path/to/asset/document.pdf");

     // to get an existing asset
     Asset asset = assetManager.getAsset("/path/to/asset/document.pdf");

     // to get asset by adapting
     Asset asset = resource.adaptTo(Asset.class);
 

Asset properties can be retrieved or set by adapting it to a ValueMap.

     eg:
     // to get Asset properties value map
     ValueMap map = asset.adaptTo(ValueMap.class);

I hope this helps!!

VJain03Author
April 23, 2024

Thank you for your reply @sravs 
But its giving NullPointerException at 

 Asset newAsset = assetManager.createAsset("/path/to/asset/document.pdf"); 
sravs
Community Advisor
Community Advisor
April 23, 2024

Can you please share your code snippet here.

aanchal-sikka
Community Advisor
Community Advisor
April 23, 2024

@vjain03 

 

The adaptTo is null, because the resource is not of type dam:Asset.

Similar discussion at: https://stackoverflow.com/questions/44807635/aem-junit-test-with-a-dam-asset

Aanchal Sikka
VJain03Author
April 23, 2024

Thanks for the reply @aanchal-sikka 

Here the resoure is of type dam:Asset
and i have checked 

DamUtil.isAsset(resource);

and its returning true

but for 

Asset asset = resource.adaptTo(Asset.class);

System.out.println(asset.getPath()); // Output: asset path: null 

if the Asset is imported from "import com.day.cq.dam.api.Asset;" then its adapting properly
but when Asset is imported from "import com.adobe.granite.asset.api.Asset;" then its giving null
request you to please solve this

EstebanBustamante
Community Advisor and Adobe Champion
Community Advisor and Adobe Champion
April 24, 2024

There are 2 ways to "mock" this type of "Asset.class", what I've read so far in your replies is that you are mixing both. Here are the options:

1) You use a mocked resourceResolver and then you must mock each method that will be invoked by this object (especially the adapTo) and manually return another mock object, and the cycle repeats.

2) You use aemContext.resourceResolver() and configure it to be adapted to a AssetManager.class, 

My recommendation would be to go with method #2.

Usually, you would do something like this:

@Mock private AssetManager mockAssetManager; private AemContext context = new AemContext(); @BeforeEach void setUp() { MockitoAnnotations.openMocks(this); //This will register the adapTo(AssetManager) context.registerAdapter(ResourceResolver.class, AssetManager.class, mockAssetManager); } @Test void test_example() { Asset asset = context.resourceResolver().getResource("/path/to/your/asset").adaptTo(Asset.class); when(AssetManager.getAsset("/path/to/your/asset")).thenReturn(asset); }

 

Check these references:

https://medium.com/@jlanssie/create-a-custom-workflow-model-in-aem-with-a-full-code-coverage-unit-test-4178b2263b81

https://taylor.callsen.me/unit-testing-aem-sling-models-and-servlets/

 

Hope this helps

Esteban Bustamante
VJain03Author
April 24, 2024

Thank you for your reply @estebanbustamante 
Below code is giving null 
please check it

public class WorkflowTest {
    @Mock
    AssetManager mockAssetManager;
    private AemContext aemContext=new AemContext();
    @BeforeEach
    public void setup()
    {
    MockitoAnnotations.openMocks(this);
    aemContext.registerAdapter(ResourceResolver. class, AssetManager. class, mockAssetManager);
    aemContext.load().json("/com/test.json","/content");
}
    @Test
    public void test_example()
    {
  Asset asset=aemContext.resourceResolver().getResource("/content/test.mp4").adaptTo(Asset.class);   //Null if we use import "import com.adobe.granite.asset.api.Asset" but notNull if we use import "import com.day.cq.dam.api.Asset;"
    assertNotNull(asset);
    when(mockAssetManager.getAsset("content/test.mp4"))thenReturn(asset);  
}
}
request you to please solve this error
EstebanBustamante
Community Advisor and Adobe Champion
EstebanBustamanteCommunity Advisor and Adobe ChampionAccepted solution
Community Advisor and Adobe Champion
April 24, 2024

Correct. It will return null if you use the com.adobe.granite.asset.api.Asset because it is not adaptable. Why are you using that? You should use the Asset implementation from com.day.cq.dam.api.Asset.

If you really want to stick with the other Asset implementation, you need to mock that class and not rely on the aemContext object. That's what I suggested as option #1 in my previous response. You should mock all of the following objects: ResourceResolver, the AdaptTo method, the AssetManager, and the Asset. The drawback with this approach is that you are not testing anything because you are setting the expected value at each step. 

** Updated Response 10/07/25 **
As pointed out by @jackki2, the implementation should not be changed to simplify writing test cases. You should prefer using com.adobe.granite.asset.api.Asset whenever possible, as it is an upper abstraction in the general AEM stack

 

 

Hope this helps

 

 

Esteban Bustamante