javajunitaemsling

"resource.adaptTo" NullPointer Unit test AEM Sling Model Java


I'm doing a pretty basic Unit test for Sling Model in AEM, so, when I run the test I get the following error:

[ERROR] CtaModelTest.testGetText:36 NullPointer

This is my Java code, the Model is a very basic Sling AEM Model, I'm using the @ModelAnnotation as follow:

@Model(adaptables = SlingHttpServletRequest.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
package com.myproject.core.models;
import org.apache.commons.lang3.StringUtils;
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 com.day.cq.wcm.api.Page;
import io.wcm.testing.mock.aem.junit5.AemContext;
import io.wcm.testing.mock.aem.junit5.AemContextExtension;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import junitx.util.PrivateAccessor;
import javax.inject.Inject;

@ExtendWith(AemContextExtension.class)
class CtaModelTest {
    private static final String COMPONENT_PATH = "/content/campaigns/myproject/master/demo-campaign/demo-email";
    
    private CtaModel ctaModel;

    private Page page;
    private Resource resource;

    @BeforeEach
    public void setup(AemContext context) throws Exception {
        
        context.load().json("/ctaModelTest.json", COMPONENT_PATH);
        context.addModelsForClasses(CtaModel.class);
        
        resource = context.resourceResolver().getResource(COMPONENT_PATH + "/jcr:content/par/hero/cta");
        ctaModel = resource.adaptTo(CtaModel.class);
    }

    @Test
    void testGetText() throws Exception {
        String txt = ctaModel.getText();
        assertNotNull(txt);
    }
}

Can anyone help me to fix it?


Solution

  • It seems that resource.adaptTo(CtaModel.class) returned null. The problem is, that adaptTo(...) returns null very silently, if anything fails. Therefore the SlingMocks documentation recommends ModelFactory.createModel(...) instead of adaptTo(...) for SlingModels.

    https://sling.apache.org/documentation/development/sling-mock.html#model-instantiation

    // load some content into the mocked repo
    context.load().json(..., "/resource1");
    
    // load resource
    Resource myResource = content.resourceResolver().getResource("/resource1");
    
    // instantiate Sling Model (adaptable via Resource)
    // this will throw exceptions if model cannot be instantiated
    MyModel myModel = context.getService(ModelFactory.class).createModel(myResource, MyModel.class);
    

    If you doing this, the ModelFactory will log error-details, why the Sling model couldn't be created. So you know, what the problem is, and you don't need to guess.