Search This Blog

Saturday 28 January 2017

Unit testing AEM - Mockito and AEM mock examples


Example projects


  1.  https://github.com/wcm-io/wcm-io-samples
  2.  https://github.com/wcm-io/


Combination of Mockito and AEM Mocks


  1. https://github.com/wcm-io/wcm-io-config/blob/develop/editor/src/main/java/io/wcm/config/editor/impl/EditorParameterPersistence.java
  2. https://github.com/wcm-io/wcm-io-config/blob/develop/editor/src/test/java/io/wcm/config/editor/impl/EditorParameterPersistenceTest.java 


Unit testing AEM - AEM mocks

AEM mocks

Basically personalized version of mocks for AEM instead of sling/osgi/jcr mocks.

Sling mock

Osgi mock

JCR mock

AEM mocks

The 
AemContext object provides access to mock implementations of:
·       OSGi Component Context
·       OSGi Bundle Context
·       Sling Resource Resolver
·       Sling Request
·       Sling Response
·       Sling Script Helper
Additionally, it supports:
·       Registering OSGi services
·       Registering adapter factories
·       Accessing JSON Importer




Mocked api can be found here.



The Mocktagmanager class for aemcontext can be found at this location

Important to note here is that the move operation cannot be mocked since it throws unsupportedoperationsexception.


AEM Mock example:

Resource resolver can be obtained like
 context.resourceResolver();
which can then be used to get/adapt to other objects as with actual API.

Example.
 context.resourceResolver().adaptTo(TagManager.class); 

--------------------------------------------------------------------------------------------------------------------------


Aem context can be used for creating aem pages, tags,nodes etc. As shown below.

Getting and Manipulating Pages

Example for accessing AEM API for reading and writing data:
public class ExampleTest {

  @Rule
  public final AemContext context = new AemContext();

  @Test
  public void testSomething() {
    Page page = context.pageManager().getPage("/content/sample/en");
    Template template = page.getTemplate();
    Iterator<Page> childPages = page.listChildren();
    // further testing
  }

  @Test
  public void testPageManagerOperations() throws WCMException {
    Page page = context.pageManager().create("/content/sample/en", "test1",
        "/apps/sample/templates/homepage", "title1");
    // further testing
    context.pageManager().delete(page, false);
  }

}


Manipulating/Creating Tags

@SuppressWarnings("unused")
    private void mockRegionsNew() throws PersistenceException {
        Resource regionNewResource = context.create().resource(
                MSRPConstants.ETC_REGIONS_NEW_NODE,
                ImmutableMap.<String, Object> builder().put("prop1", "value1")
                        .build());

        Resource a = context.resourceResolver().create(regionNewResource, "a",null);
        Resource e = context.resourceResolver().create(regionNewResource, "e",null);
        Resource b = context.resourceResolver().create(e, "b", null);
        // Resource c = context.resourceResolver().create(b, "c", null);
        Resource d = context.resourceResolver().create(b, "d", null);

        // return regionNewResource;
    }

Resources/Nodes

@SuppressWarnings("unused")
    private void mockRegionsNew() throws PersistenceException {
        Resource regionNewResource = context.create().resource(
                MSRPConstants.ETC_REGIONS_NEW_NODE,
                ImmutableMap.<String, Object> builder().put("prop1", "value1")
                        .build());

        Resource a = context.resourceResolver().create(regionNewResource, "a",
                null);
        Resource e = context.resourceResolver().create(regionNewResource, "e",
                null);
        Resource b = context.resourceResolver().create(e, "b", null);
        // Resource c = context.resourceResolver().create(b, "c", null);
        Resource d = context.resourceResolver().create(b, "d", null);

        // return regionNewResource;
    }

AEM Mocks pom.xml snippet


<dependency>
<groupId>io.wcm</groupId>
<artifactId>io.wcm.testing.aem-mock</artifactId>
<!--for AEM 6.0 or 6.1 use version 1.x for 6.2 use 1.x or above-->
<version>2.1.0</version>
<scope>test</scope>
</dependency>


Used in UNHCR/pom.xml


<!-- AEM Mock -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-imaging</artifactId>
    <version>1.0-R1534292</version>
</dependency>
         <dependency>
       <groupId>io.wcm</groupId>
       <artifactId>io.wcm.testing.aem-mock</artifactId>
       <version>1.3.0</version>
       <scope>test</scope>
   </dependency>

<!-- Sling Mocks -->
<dependency>
    <groupId>org.apache.sling</groupId>
    <artifactId>org.apache.sling.testing.resourceresolver-mock</artifactId>
    <version>1.1.4</version>
    <scope>test</scope>
  </dependency>
<dependency>
    <groupId>org.apache.sling</groupId>
    <artifactId>org.apache.sling.testing.osgi-mock</artifactId>
    <version>1.2.0</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.apache.sling</groupId>
    <artifactId>org.apache.sling.testing.jcr-mock</artifactId>
    <version>1.1.4</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.apache.sling</groupId>
    <artifactId>org.apache.sling.testing.sling-mock</artifactId>
    <version>1.2.0</version>
    <scope>test</scope>
</dependency>

commons-imaging

This commons-imaging library is required for 2.x version of aem-mock.
unfortunately there is still no official release of the commons-imaging library. 

the unofficial build 1.0-R1725432 that we reference can be found here: 
http://wcm.io/maven/repositories/apache-intermediate-release/ 


sling mock

dependencies also might be required for AEM mocks so better to include them.

Unit testing AEM - Mocking with Mockito


Documentation - http://mockito.github.io/mockito/docs/current/org/mockito/Mockito.html
Mockito is a Java mocking library which is very useful in unit testing but also to simplify and enhance the integration tests.


Mockito Example –
 
Public class MyService{
Public String readData(ResourceResolverresolver, String path) {
Resourcer= resolver.getResource(path);
returnr== null? null: r.adaptTo(String.class);
}
}

@Test
publicvoidtestReadData() {
ResourceResolverresolver= mock(ResourceResolver.class);
Resourcer src= mock(Resource.class);
when(resolver.getResource("/content/data/testdata")).thenReturn(rsrc);
when(rsrc.adaptTo(String.class)).thenReturn("OK");
MyServiceservice= newMyService();
assertEquals("OK", service.readData(resolver, "/content/data/testdata"));
}

OR  use @mock annotation and mock using initmocks().
public class TestBaseListModel {

    @Mock
    private ResourceResolver resourceResolver;

    @Mock
    private PageManager pageManager;

    @Mock
    private LinkBean linkBean;

    @Mock
    private Resource resource;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
                             ….