Expand my Community achievements bar.

SOLVED

junit with AemContextExtension

Avatar

Level 3

Hi I am trying to write junit using aem context for the first time, below is my sample sling model class.

 

@Model(adaptables = Resource.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class HeadlineModel {
private static final Logger LOGGER = LoggerFactory.getLogger(HeadlineModel.class);
@ValueMapValue
@Optional
private String size;
@ValueMapValue
@Optional
private String alignment;
@ValueMapValue
@Optional
private String headlinetext;
@ValueMapValue
@Optional
private String scheme;

public String getSize() {
return size;
}

public String getAlignment() {
return alignment;
}

public String getHeadlinetext() {
return headlinetext;
}

public String getScheme() {
return scheme;
}
}

Could someone give example to mock the above getters with latest way of using aemcontext

 

1 Accepted Solution

Avatar

Correct answer by
Employee Advisor

I have given an example how to unittest a sling model at https://cqdump.wordpress.com/2019/01/17/writing-unittests-for-aem-part-3-mocking-resources/, it should answer your questions.

 

Jörg

View solution in original post

3 Replies

Avatar

Community Advisor

@srikanthg212933,

Sure. There are really good resources online that should help you get started. Try here https://sourcedcode.com/category/aem/junit4

Original Blog: https://sourcedcode.com/aem-sling-models-unit-test-junit-4-with-examples

 

Header.class

package com.sourcedcode.core.models;

import com.day.cq.wcm.api.Page;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.ChildResource;
import org.apache.sling.models.annotations.injectorspecific.ScriptVariable;
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;

import javax.annotation.PostConstruct;
import javax.inject.Inject;

@Model(adaptables = Resource.class,
        resourceType = Header.RESOURCE_TYPE,
        defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class Header {

    protected static final String RESOURCE_TYPE = "sourcedcode/components/structure/header";

    @ValueMapValue
    private String contactUsPath;

    @ScriptVariable(name="currentPage")
    private Page currentPage;

    @ChildResource(name="link")
    Resource childResource;

    @SlingObject
    private ResourceResolver resolver;

    private String contactUsPageSecretChar;

    @PostConstruct
    public void init() {
        setContactUsPageSecretChar();
    }

    private void setContactUsPageSecretChar() {
        Resource resource = resolver.getResource(contactUsPath);
        if (resource != null) {
            Page contactUsPage = resource.adaptTo(Page.class);
            contactUsPageSecretChar = contactUsPage.getTitle();
        }
    }

    public String getContactUsPageSecretChar() {
        return contactUsPageSecretChar.substring(contactUsPageSecretChar.length() - 1);
    }

    // demo of testing the @ScriptVariable("currentPage") annotation
    public String getPageTitle() {
        return currentPage.getPageTitle();
    }

    // demo of testing the @ChildResource annotation
    public String getChildLinkPropFlag() {
        return childResource.getValueMap().get("flag", "");
    }
}

HeaderTest.class

package com.sourcedcode.core.models;

import com.adobe.cq.commerce.common.ValueMapDecorator;
import com.day.cq.wcm.api.Page;
import com.google.common.collect.ImmutableMap;
import io.wcm.testing.mock.aem.junit.AemContext;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.testing.mock.sling.ResourceResolverType;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

import static junitx.framework.Assert.assertEquals;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class HeaderTest {

    @Rule
    public final AemContext context = new AemContext(ResourceResolverType.JCR_MOCK);

    // the context.resourceResolver() is auto injected by the AemContext, cannot be mocked.
    // ResourceResolver resolver;

    // mocking the global AEM object "currentPage".
    // variable does not need to match the variables in the underTest.class
    @Mock
    private Page currentPage;

    // injects all the mocks into the tested object.
    @InjectMocks
    private Header underTest;

    @Test
    public void itShouldReturnTheCorrectSecretCharWhenResourceExist() {
        // using the AEM context to create an AEM resource in the context, to set properties for the resource.
        // the resource path can be anything made up.
        Resource headerResourceContext = context.create().resource("/content/sourcedcode/home/jcr:content/header", new ValueMapDecorator(ImmutableMap.<String, Object> of(
                "contactUsPath", "/content/sourcedcode/contact",
                "anotherProperty", "example")));

        // create mock page, resolved by the resolver.
        context.create().page("/content/sourcedcode/contact", "", ImmutableMap.<String, Object>builder()
                .put("jcr:title", "Contact Us Page")
                .build());

        underTest = headerResourceContext.adaptTo(Header.class);
        assertEquals("e", underTest.getContactUsPageSecretChar());
    }

    @Test
    public void itShouldReturnTheCorrectCurrentPageTitle() {
        when(currentPage.getPageTitle()).thenReturn("Home Page");
        assertEquals("Home Page", underTest.getPageTitle());
    }

    @Test
    public void itShouldReturnTheCorrectChildLinkProperty() {
        context.build().resource("/content/sourcedcode/home/jcr:content/header")
                .siblingsMode()
                .resource("link", "flag", "newPage");
        underTest = context.resourceResolver().getResource("/content/sourcedcode/home/jcr:content/header").adaptTo(Header.class);
        assertEquals("newPage", underTest.getChildLinkPropFlag());
    }

}

Avatar

Correct answer by
Employee Advisor

I have given an example how to unittest a sling model at https://cqdump.wordpress.com/2019/01/17/writing-unittests-for-aem-part-3-mocking-resources/, it should answer your questions.

 

Jörg

Avatar

Community Advisor

Hi @srikanthg212933 ,

 

You can refer the sample hello world test class to achieve this.

@ExtendWith(AemContextExtension.class)
class HelloWorldModelTest {

private HelloWorldModel hello;

private Page page;
private Resource resource;

@BeforeEach
public void setup(AemContext context) throws Exception {

// prepare a page with a test resource
page = context.create().page("/content/mypage");
resource = context.create().resource(page, "hello",
"sling:resourceType", "myproject/components/content/helloworld");

// create sling model
hello = resource.adaptTo(HelloWorldModel.class);
}

@Test
void testGetMessage() throws Exception {
// some very basic junit tests
String msg = hello.getMessage();
assertNotNull(msg);
assertTrue(StringUtils.contains(msg, resource.getResourceType()));
assertTrue(StringUtils.contains(msg, page.getPath()));
}

}

 

Regards,

Santosh