Expand my Community achievements bar.

SOLVED

Issue testing Sling Model that contain @ParentResourceValueMapValue annotations

Avatar

Level 2

Hi all,

I'm trying to test a model that uses the  @ParentResourceValueMapValue on its properties (see snippet below)

@Model(

  adaptables = {SlingHttpServletRequest.class, Resource.class},

  adapters = {ArticleInfo.class, Component.class, ComponentExporter.class},

  resourceType = ArticleInfoImpl.RESOURCE_TYPE,

  defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL

)

@exporter(

  name = ExporterConstants.SLING_MODEL_EXPORTER_NAME,

  extensions = ExporterConstants.SLING_MODEL_EXTENSION

)

@getter

public class ArticleInfoImpl extends com.ally.components.core.internal.models.v1.ComponentImpl implements ArticleInfo {

 

  protected static final String RESOURCE_TYPE = "contenthub/components/content/articleinfo/v1/articleinfo";

  private final Logger log = LoggerFactory.getLogger(this.getClass().getName());

  private static final String DATE_FORMAT = "MM/dd/uuuu";

 

  @ParentResourceValueMapValue

  private String customPubDate;

 

  @ParentResourceValueMapValue

  private String customModDate;

 

  @ParentResourceValueMapValue

  private String contentLength;

 

  @ParentResourceValueMapValue

  private String contentType;

 

  @ParentResourceValueMapValue

  private String authorContentFragmentPath;

  

  //For STOR-43776

  //NB: The name and type may change need to work with Cherub on this

  @ParentResourceValueMapValue

  private String customPubDateSelection;

  

  @ParentResourceValueMapValue

  private String customModDateSelection;

 

 

  private String authorName = "";

 

  @inject

  private ContentTypeConverter contentTypeConverter;

  

  @inject

  private DateService dateService;

 

  @SlingObject

  private ResourceResolver resourceResolver;

 

  @PostConstruct

  public void initModel() {

    super.initModel();

 

    if (authorContentFragmentPath != null) {

      Resource pathResource = resourceResolver.getResource(authorContentFragmentPath);

      ContentFragment authorFragment = pathResource.adaptTo(ContentFragment.class);

      String modelPath = "global/models/person";

      String[] elementNames = new String[] { "firstName", "lastName" };

 

      if (ContentFragmentUtils.getType(authorFragment).equals(modelPath)) {

        log.info("Content fragment matches specified type of " + modelPath);

 

        DAMContentFragment authorFragmentModel = new DAMContentFragmentImpl(pathResource, contentTypeConverter, null, elementNames);

 

        String firstName = "";

        String lastName = "";

 

        firstName = java.util.Optional.ofNullable(authorFragmentModel.getElements().get(0).getValue()).orElse("").toString();

        lastName = java.util.Optional.ofNullable(authorFragmentModel.getElements().get(1).getValue()).orElse("").toString();

 

        if(lastName == "") {

          authorName = firstName;

        } else {

          authorName = firstName + " " + lastName;

        }

      } else {

        log.warn("Content fragment does not match the specified type of " + modelPath);

      }

    }

  }

 

When I try to setup a Junit Test for this I continue to get the following error

Unable to create model class com.ally.components.contenthub.internal.models.v1.content.ArticleInfoImpl

at org.apache.sling.models.impl.ModelAdapterFactory.internalCreateModel(ModelAdapterFactory.java:390)

...

Caused by: java.lang.IllegalArgumentException: No Sling Models Injector registered for source 'parent-valuemap-value'.

at org.apache.sling.models.impl.ModelAdapterFactory.injectElement(ModelAdapterFactory.java:502)

 

Here's the Unit test setup...

@TestInstance(Lifecycle.PER_CLASS)

class ArticleInfoImplTest extends ComponentTest {

protected final static String ARTICLE_PAGE_JSON = "/content/dam/ArticlePage.json";

 

ArticleInfo articleInfo;

 

AemObjectInjector aemObjectInjector = new AemObjectInjector();

 

@BeforeAll

void setUpBeforeClass() {

    initializeAemContext();

    context.addModelsForClasses(ArticleInfoImpl.class);

    context.load().json(ARTICLE_PAGE_JSON, BASIC_PAGE);

    context.registerService(AemObjectInjector.class, aemObjectInjector);

    context.registerInjectActivateService(new DateServiceImpl());

    context.registerService(ContentTypeConverter.class, new MockContentTypeConverter());

    articleInfo = adaptToClass(BASIC_PAGE + "/jcr:content/root/main/article", ArticleInfo.class);

}

 

@test

void test() {

assertNotNull(articleInfo);

}

 

}

 

I'm registering an injector on 4th line of the Setup.  

Why does the system not recognize it per the Stack Trace?

 

Thanks in advance for any help.

1 Accepted Solution

Avatar

Correct answer by
Employee Advisor

The ParentResourceValueMapInjector is part of ACS AEM Commons, and it is not registered as part of the AEM Mocks. You should instantiate that service and register it in the context.

View solution in original post

5 Replies

Avatar

Community Advisor

The model should use adaptables either as SlingHttpServletRequest.class or Resource.class and should not use both.

Avatar

Correct answer by
Employee Advisor

The ParentResourceValueMapInjector is part of ACS AEM Commons, and it is not registered as part of the AEM Mocks. You should instantiate that service and register it in the context.

Avatar

Level 2

Hi,

That is actually the main issue here.  I cannot figure how to register the injector from ACS AEM Commons.  I'd appreciate any help with how to do that.

 

Thanks for your help

-Garrett

Avatar

Level 1

HI @gdeacon @Jörg_Hoh 

Did you succeed to register the Injector from ACS AEM Commons?  Did you solve the issue somehow with testing the model that contains the  annotation 

ParentResourceValueMapValue

Thank you in advance

Best

Avatar

Community Advisor

Hello @gdeacon ,
Can you follow this article? Hope this will serve your purpose. Especially the 2nd method(Language Navigation example)

https://sadyrifat.medium.com/aem-unit-test-case-for-sling-delegation-pattern-1f011b947fb3