Friday, December 9, 2016

How to Write Tests in AEM

Use Case: Writing tests for AEM application.

Current Issue: As your project and code base grows, it is really important to make sure that test coverage for code is there to maintain consistency and sanity of your code. Writing test cases for AEM is little bit different than writing conventional Java test cases, This makes it difficult for beginner to write test cases for AEM application.

Idea of this post to give different options available for writing unit test for AEM services.

Prerequisite:
Good to know:
I would explain how you can have better test coverage for your application by giving different use cases,

Dependencies: It is recommended to have following dependencies in to your pom before start writing for tests for your application
Case 1: Writing test cases for Generic Helper class.

This is simplest use case where your generic helper class (For example StringUtils, DateUtils) is not using any AEM libraries. For this you can simply use Junit to write your unit test. https://www.tutorialspoint.com/junit

Here is very simple example:


Case 2: Writing test cases for AEM Helper class

This is second use case where you want to test AEM helper methods. For this you can use combination of Junit and Mockito. Use Mockito to Mock AEM services and methods and Junit for assertion.

Here is simple example

Case 3: Writing test cases for AEM services

Now it gets little bit tricky where you need to mock certain behavior of bundle and implicit object. That's why Sling has created Mock version of sling objects and wcm.io has created mock version of AEM objects. You can just use aem mock http://wcm.io/testing/aem-mock/ to achieve most of your use cases. (AEM mock extend Sling mock).

here are some of the common use cases you will come across while testing your service.

1) How can I mock content my service is running against ?

For this it is recommended to use contentLoader API http://wcm.io/testing/aem-mock/usage.html to either load existing json based resource (You can simply get it by creating resource in CRXDE and then using something like RESOURCEPATH.infinity.json to get json for that resource) or just create mock resource using ContentBuilder context.create().resource() or ResourceBuilder context.build().resource() http://wcm.io/testing/aem-mock/apidocs/

Note that if you are mocking Page object then you have to use aem mock using aemcontext.pageManager().create()

2) How Can I initialize properties in the bundle ?

You can use register and activate OSGI service with properties http://wcm.io/testing/aem-mock/usage.html#Registering_OSGi_service for that. Here is some example


3) How Can I inject other service for my service ?

You can either Mock service or use register service API for that http://wcm.io/testing/aem-mock/usage.html#Registering_OSGi_service

Note that when you inject a service to your service using Reference then you have to register this your injected service, otherwise your test will fail.

4) How Can I test sling model ?

You can use aemContext for that. http://wcm.io/testing/aem-mock/usage.html#Sling_Models


Case 4: Writing test cases for AEM servlets and filters

This is very similar to how you would do test cases for Service. For request and response you either have to mock request / response object using Mockito or Use Spy  or use sling request and response mock. Since a lot of methods in filter and servlet do not return any result, Make Mockito verify your friend.  Here is one example using simple mockito to test servlet



 How can I measure my test coverage ?

 You can use jococo test coverage plugin along with your build system to measure this coverage. You can have following plugin in to your parent pom



How Can I write Integration test in AEM ?

Very good example here https://github.com/sneakybeaky/AEM-Integration-Test-Example

It is based of sling test base https://sling.apache.org/documentation/development/sling-testing-tools.html

I know this information is not enough to have you set up for writing tests in AEM. Feel free to let me know if you have more question and I will add more stuff here.

Sunday, February 7, 2016

How to Sightly in AEM / CQ

Use Case: Some common how to in Sightly

Prerequisite: Please read following document carefully before some other How to questions

Here is some common How to in sightly


  • How to include ClientLibs in Sightly 


  • How to Loop fixed number of set in Sightly 


  • How to create for or while loop in sightly

You can not have dynamic while loop directly in Sightly scripting. However you can use Use class to simulate while or for loop in Sightly. Here is example

  • How to reference other OSGI service in sightly 

You can not directly reference OSGI service in sightly template. However you can reference them in use class using getSlingScriptHelper().getService(Service.class) note that you can not use @Reference to refer a service in sightly class.

  • How to initialize a default value of a property in sightly

Best way to initialize a value is in activate method of use class. You can also do it in sightly template using something like <sly data-sly-test.parentNavName="${currentPage.properties.navTitle || currentPage.title || currentPage.pageTitle }"> and then use ${parentNavName}
  • How to access string array in Sightly 

This is pretty much similar to what we did in for loop. Here is some more generic example

  • How to create/access map in sightly 

Here is one example of how you can do that

  • How to use Sling Model with Sightly

Here is one example of how you can do it. Note that You can also create sling model for a resource and then use other use classes to return sling model.


  • How to hide element in Sightly

You can use either data-sly-unwrap or <sly> tag for this here is example
<!--/* This will only show "Foo" (without a <div> around) if the test is true: */-->
<div data-sly-test="${myTest}" data-sly-unwrap>Foo</div>

<!--/* This would show a <div> around "Foo" only if the test is false: */-->
<div data-sly-unwrap="${myTest}">Foo</div>
<!--/* This will display only the output of the 'header' resource, without the wrapping <sly> tag */-->
<sly data-sly-resource="./header"></sly>
<sly data-sly-unwrap="${false}"></sly> <!--/* outputs: <sly></sly> */-->

  • How to pass a sightly object as parameter in Sightly

More use cases to come. Please suggest me any use case you want to get clarity on.

Some more useful Link:

Tooling For Sightly:

Friday, January 29, 2016

How to perform Tree Activation in CQ AEM

Use Case: You want to tree activate a page as part of your code or scheduler

Example:

Replication Helper Class

 

Tree Activation Service

Tree Activation Impl



Note: In above example replication action is performed using admin user. You could also create a replication user and use that user to replicate instead.