Expand my Community achievements bar.

Don’t miss the AEM Skill Exchange in SF on Nov 14—hear from industry leaders, learn best practices, and enhance your AEM strategy with practical tips.
SOLVED

AemMock is not able to return page.getTemplate() in a Model adaptable to SlingHttpServletRequest

Avatar

Level 2

I am trying to test a Model adaptable as SlingHttpServletRequest. Its basically a Custom RenderCondition checks for the Template of the page to show or hide dialog field/tab. It will be a great help if anyt one could point any issue in my test fixture, following the documents from io.wcm here - https://wcm.io/testing/aem-mock/usage.html#JUnit_4_AEM_Context_JUnit_Rule it should work on page.getTemplate() after adapting resource as Page.

I Now the test cases are failing Due to its not able to get the page.getTemplate(); it always returns Null but at the same time if I use resource API its can get "cq:template" as string and passes the test.

 

package com.abc.models;

import com.adobe.cq.sightly.WCMBindings;
import com.adobe.granite.ui.components.rendercondition.RenderCondition;
import com.adobe.granite.ui.components.rendercondition.SimpleRenderCondition;
import com.amex.gem.AppAemContext;
import com.day.cq.wcm.api.*;
import com.google.common.collect.ImmutableMap;
import io.wcm.testing.mock.aem.junit.AemContext;
import io.wcm.testing.mock.aem.*;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.scripting.SlingBindings;
import org.apache.sling.models.factory.ModelFactory;
import org.apache.sling.testing.mock.sling.servlet.MockSlingHttpServletRequest;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

@RunWith(MockitoJUnitRunner.class)
public class TemplateTypeRenderConditionTest {

    private static final String DEST_ROOT = "/content/sample/abc";
    private static final String TEMPLATE_PATH = "/conf/homepage/settings/wcm/templates/homepage";
    private static final String PAGE_ROOT = "/content/sample/abc/index";
    private TemplateTypeRenderCondition underTestModel;
    public final AemContext CONTEXT = AppAemContext.newAemContext();

    @Mock
    PageManager pageManager;
    SlingBindings slingBindings;
    Resource pageResource ;
    Page pageToTest = null;

    @Before
    public void setUp() throws NoSuchFieldException, WCMException {


        slingBindings = (SlingBindings) CONTEXT.request().getAttribute(SlingBindings.class.getName());
        slingBindings.put(WCMBindings.PAGE_MANAGER, pageManager);

         slingBindings.put(SlingBindings.RESOURCE, CONTEXT.resourceResolver().getResource(DEST_ROOT));
         CONTEXT.request().setAttribute(SlingBindings.class.getName(), slingBindings);

         // prepare sling request
         CONTEXT.request().setResource(CONTEXT.resourceResolver().getResource(DEST_ROOT));
         CONTEXT.request().setQueryString("item=/content/sample/abc/index");

         CONTEXT.pageManager().create("/content/sample/abc", "index", TEMPLATE_PATH, "title1");

    }
    
    public void itShouldReturnTheResourceMatchesTheTemplateTypeFromItemParamter() throws WCMException {
        
        CONTEXT.pageManager().create("/content/sample/abc", "index", TEMPLATE_PATH, "title1");
        pageResource = CONTEXT.resourceResolver().getResource(PAGE_ROOT);
        pageToTest = CONTEXT.pageManager().getPage(PAGE_ROOT);
        underTestModel = CONTEXT.getService(ModelFactory.class).createModel(CONTEXT.request(), TemplateTypeRenderCondition.class);
        assertEquals(pageToTest.getTemplate().getPath(),TEMPLATE_PATH);
        assertEquals(pageToTest.getResource().getValueMap().get("cq:template", String.class), TEMPLATE_PATH);

    }

}

 

The first assert is failing for getting template object but not the second one. Saying .getTemplate is returning null

 

My Unit test passes this assert

 

underTestModel = CONTEXT.getService(ModelFactory.class).createModel(CONTEXT.request(), TemplateTypeRenderCondition.class);
SimpleRenderCondition resultingRenderCond = (SimpleRenderCondition)  CONTEXT.request().getAttribute(RenderCondition.class.getName());
assertTrue(resultingRenderCond.check());

 

If I am using this code to get the Template in my class:

 

final Resource pageResource = page.getContentResource();
templatePathOfCurrentPage = pageResource.getValueMap().get("cq:template", String.class);

 

But fails if the AEM Page API being used for accessing template name:

 

          final Template pageTemplate = page.getTemplate();
          templatePathOfCurrentPage = pageTemplate.getPath();

 

 

Class under test:

 

package com.abc.models;

import com.adobe.granite.ui.components.rendercondition.RenderCondition;
import com.adobe.granite.ui.components.rendercondition.SimpleRenderCondition;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageManager;
import com.day.cq.wcm.api.Template;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.ScriptVariable;
import org.apache.sling.models.annotations.injectorspecific.Self;
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.PostConstruct;
import java.util.Arrays;
import java.util.List;

@Model(adaptables = SlingHttpServletRequest.class)
public class TemplateTypeRenderCondition {
    private final Logger logger = LoggerFactory.getLogger(TemplateTypeRenderCondition.class);


    
    private SlingHttpServletRequest request;

    @ScriptVariable
    private PageManager pageManager;

    @ValueMapValue
    private String[] templatePath;

    @PostConstruct
    public void init() {

        // Get the resource page path for which propery is being edited
        final String pathPage = request.getParameter("item");

        //Assign suffix as path for Create Page wizard
        final String suffix = request.getRequestPathInfo().getSuffix();;


        // Still cannot found the through exception
        if (pathPage == null && suffix == null) {
            throw new IllegalArgumentException("Could not determine page from <" + request.getPathInfo() + "> , neither suffix in create page wizard or, item in editor");
        }
        logger.info("Path Info for the page property editing from RenderCondition is {}", request.getPathInfo());

        String templatePathOfCurrentPage = null;
        if(pathPage != null) {
            final Page page = pageManager.getPage(pathPage);
            if (page == null) {
                throw new IllegalArgumentException("Resource at <" + pathPage + "> is not a page");
            }

            //Failing with this code
            // final Template pageTemplate = page.getTemplate();
            //templatePathOfCurrentPage = pageTemplate.getPath();
            final Resource pageResource = page.getContentResource();
            templatePathOfCurrentPage = pageResource.getValueMap().get("cq:template", String.class);
        } else if( suffix != null){
            templatePathOfCurrentPage = suffix;
        }

        // Check if we have the template from page
        if(templatePath.length < 1) {
                throw new IllegalArgumentException("Could not get page template match from <" + request.getPathInfo() + ">");
        }
        final List<String> listTemplates = Arrays.asList(templatePath);
        final boolean show = listTemplates.contains(templatePathOfCurrentPage);


        // Add the render condition based on check if list of templatePath has current page template allowed
        request.setAttribute(RenderCondition.class.getName(), new SimpleRenderCondition(show));
    }

    public String[] getTemplatePath(){
        return templatePath;
    }

}

 

 

 I am trying to test it and so here is my Context setup for test:

 

package com.abc;

import com.abc.models.TemplateTypeRenderCondition;
import com.google.common.base.Function;
import io.wcm.testing.mock.aem.junit.AemContext;
import io.wcm.testing.mock.aem.junit.AemContextCallback;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.testing.mock.sling.ResourceResolverType;

import javax.annotation.Nullable;

public class AppAemContext {

    private static final String DEST_ROOT = "/content/sample/abc";
    private static final String TEST_JSON = "/templaterendercond/test-content.json";
    private static final String PAGE_ROOT = "/content/sample/abc/index";
    private static final String TEST_PAGE_JSON = "/templaterendercond/test-page.json";

    public static AemContext newAemContext() {
        return new AemContext(new SetUpCallback(), ResourceResolverType.JCR_MOCK);
    }

    private static TemplateTypeRenderCondition mockTemplateTypeRenderCondition  = new TemplateTypeRenderCondition();

    private static final class SetUpCallback implements AemContextCallback {

        
        public void execute(AemContext context) {
            context.registerAdapter(SlingHttpServletRequest.class,
                    TemplateTypeRenderCondition.class,
                    new Function<SlingHttpServletRequest, TemplateTypeRenderCondition>() {

                
                public TemplateTypeRenderCondition apply(@Nullable SlingHttpServletRequest request) {
                    return mockTemplateTypeRenderCondition;
                }
            });

            // register models from package
            context.addModelsForPackage("com.abc.models");
            context.load().json(TEST_JSON, DEST_ROOT);
            context.load().json(TEST_PAGE_JSON, PAGE_ROOT);
        }
    }
}

 

 

This is my POM fixture for Test:

 

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
		</dependency>
		<dependency>
			<groupId>junit-addons</groupId>
			<artifactId>junit-addons</artifactId>
		</dependency>
		<dependency>
			<groupId>org.mockito</groupId>
			<artifactId>mockito-all</artifactId>
		</dependency>
		<dependency>
			<groupId>org.apache.sling</groupId>
			<artifactId>org.apache.sling.api</artifactId>
			<version>2.18.4</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.sling</groupId>
			<artifactId>org.apache.sling.adapter</artifactId>
			<version>2.1.6</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.sling</groupId>
			<artifactId>org.apache.sling.jcr.api</artifactId>
			<version>2.4.0</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.sling</groupId>
			<artifactId>org.apache.sling.jcr.resource</artifactId>
			<version>3.0.18</version>
			<scope>test</scope>
		</dependency>
		<!-- for testing we need the new ResourceTypeBasedResourcePicker -->
	        <dependency>
			<groupId>org.apache.sling</groupId>
			<artifactId>org.apache.sling.models.impl</artifactId>
			<version>1.4.12</version>
			<scope>test</scope>
		</dependency>
		<!-- Added for Powemock -->
		<dependency>
			<groupId>org.powermock</groupId>
			<artifactId>powermock-module-junit4</artifactId>
		</dependency>
		<dependency>
			<groupId>org.powermock</groupId>
			<artifactId>powermock-api-mockito</artifactId>
		</dependency>

		<dependency>
			<groupId>org.powermock</groupId>
			<artifactId>powermock-api-mockito-common</artifactId>
			<version>1.7.4</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.powermock</groupId>
			<artifactId>powermock-api-mockito</artifactId>
			<version>1.7.4</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.powermock</groupId>
			<artifactId>powermock-api-easymock</artifactId>
			<version>1.5.5</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.easymock</groupId>
			<artifactId>easymock</artifactId>
			<version>3.2</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.sling</groupId>
			<artifactId>org.apache.sling.testing.osgi-mock</artifactId>
			<version>2.4.14</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.sling</groupId>
			<artifactId>org.apache.sling.testing.jcr-mock</artifactId>
			<version>1.4.4</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.sling</groupId>
			<artifactId>org.apache.sling.testing.resourceresolver-mock</artifactId>
			<version>1.1.26</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>io.wcm</groupId>
			<artifactId>io.wcm.sling.commons</artifactId>
			<version>1.3.0</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.sling</groupId>
			<artifactId>org.apache.sling.testing.sling-mock.junit4</artifactId>
			<version>2.4.0</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.sling</groupId>
			<artifactId>org.apache.sling.testing.sling-mock-oak</artifactId>
			<version>2.1.6</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>io.wcm</groupId>
			<artifactId>io.wcm.testing.aem-mock.junit4</artifactId>
			<version>3.0.0</version>
			<scope>test</scope>
		</dependency>

 

 

 

 

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

@rohan_raj1 Use the following code snippet to create mock page and page template object

//Add following code snippet

 @BeforeEach
    void setUp() throws WCMException {
        context.load().json("<PAGE_TEMPLATE_RESOURCE_JSON_PATH>", "<TEMPLATE_PATH>");
        final PageManager pageManager = context.resourceResolver().adaptTo(PageManager.class);
        context.create().page("/content/mysite/us/en/home");
        final Page currentPage = pageManager.create("/content/mysite/us/en/home",
            "sample-page",
            "<TEMPLATE_PATH>", "Page Title", true);
        context.currentPage(currentPage);
        context.currentResource(<yourComponentResource>);
        myComponentModel= (ContentHeroModelImpl) context.request().adaptTo(
            MyComponentModel.class);
    }

View solution in original post

1 Reply

Avatar

Correct answer by
Community Advisor

@rohan_raj1 Use the following code snippet to create mock page and page template object

//Add following code snippet

 @BeforeEach
    void setUp() throws WCMException {
        context.load().json("<PAGE_TEMPLATE_RESOURCE_JSON_PATH>", "<TEMPLATE_PATH>");
        final PageManager pageManager = context.resourceResolver().adaptTo(PageManager.class);
        context.create().page("/content/mysite/us/en/home");
        final Page currentPage = pageManager.create("/content/mysite/us/en/home",
            "sample-page",
            "<TEMPLATE_PATH>", "Page Title", true);
        context.currentPage(currentPage);
        context.currentResource(<yourComponentResource>);
        myComponentModel= (ContentHeroModelImpl) context.request().adaptTo(
            MyComponentModel.class);
    }