Junit test cases for AEM Event Listener | Community
Skip to main content
Level 2
October 28, 2020
Solved

Junit test cases for AEM Event Listener

  • October 28, 2020
  • 3 replies
  • 5794 views

Hello Everyone,

I need to write the junit for Event Listener. Attaching the sample code for reference. Could you please suggest the best way of writing the junit for Event Listener.

 

 

 

package myproject.core.listeners;

import java.util.HashMap;
import java.util.Map;

import javax.jcr.Node;
import javax.jcr.RepositoryException;

import javax.jcr.Session;
import javax.jcr.observation.Event;
import javax.jcr.observation.EventListener;

import org.osgi.service.component.annotations.Activate;

import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;

import org.osgi.service.component.annotations.Reference;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.day.cq.commons.Externalizer;
import myproject.core.service.EmailService;

import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.osgi.service.component.ComponentContext;
import javax.jcr.observation.EventIterator;

@8220494(immediate = true, service = EventListener.class)

public class UserNotificationListener implements EventListener {

Logger log = LoggerFactory.getLogger(this.getClass());
private Session adminSession;

String nodePath = StringUtils.EMPTY;

@3214626
org.apache.sling.jcr.api.SlingRepository repository;

@3214626
private ResourceResolverFactory resourceResolverFactory;

@3214626
Externalizer externalizer;

@3214626
private transient EmailService emailService;

@580286
public void activate(ComponentContext context) throws Exception {
log.info("activating ExampleObservation");
try {
adminSession = repository.loginService("datawrite", null);
adminSession.getWorkspace().getObservationManager().addEventListener(
this, //handler
Event.PROPERTY_ADDED | Event.NODE_ADDED, //binary combination of event types
"/home/users", //path
true, //is Deep?
null, //uuids filter
null, //nodetypes filter
false);

} catch(RepositoryException e) {
log.error("unable to register session", e);
throw new Exception(e);
}
}@Deactivate
public void deactivate() {
if (adminSession != null) {
adminSession.logout();
}
}

public void onEvent(EventIterator eventIterator) {
try {
while (eventIterator.hasNext()) {
Event event = eventIterator.nextEvent();
nodePath = event.getPath();
if (nodePath != null && nodePath.contains("email")) {
Node root = adminSession.getRootNode();
String profilepath = nodePath.substring(1, nodePath.lastIndexOf("/"));
log.info("profilepath path : {}", profilepath);
String externalurlprefix = profilepath.substring(0, profilepath.lastIndexOf("/"));
Node user_node = root.getNode(externalurlprefix);
String userName =user_node.getProperty("rep:principalName").getString();
// log.info("user_node userName" + user_node.getProperty("rep:principalName").getString());
// log.info("user_node password" + user_node.getProperty("rep:password").getString());
Node another_node = root.getNode(profilepath);
String emailAddress =another_node.getProperty("email").getString();
log.info("EmailId Node" + another_node.getProperty("email").getString());
ResourceResolver resourceResolver = null;
Map < String,Object > paramMap = new HashMap < String,Object > ();
// paramMap.put(ResourceResolverFactory.SUBSERVICE, "socialService");
paramMap.put(ResourceResolverFactory.SUBSERVICE, "datawrite");
resourceResolver = resourceResolverFactory.getServiceResourceResolver(paramMap);
String myExternalizedUrl = externalizer.authorLink(resourceResolver, "/libs/granite/security/content/v2/usereditor") + ".html/" + externalurlprefix;
Map < String,
String > emailParams = new HashMap < String,
String > ();
emailParams.put("userName", userName);
emailParams.put("recipient", emailAddress);
emailParams.put("emailSubject", "You’ve been invited to join the Intuit Asset Library.");
emailParams.put("message", "You’ve been invited to join the asset library.");
emailParams.put("passwordLinksHTML", myExternalizedUrl);
String recipientEmail = emailService.sendMail(resourceResolver, emailParams, emailAddress);
if (StringUtils.isEmpty(recipientEmail)) {
log.info("mail not sent");
} else {
log.info("mail sent successfully");
}

}

}

} catch(Exception e) {
log.error("Error while treating events", e);

}
}
}

This post is no longer active and is closed to new replies. Need help? Start a new post to ask your question.
Best answer by davidjgonzalezzzz

The cleanest way to unit test this is to simply test is an OSGi service using AEM Mocks [1]  (which are a super-set of Sling Mocks/JCR mocks [2]).

You can see how something (of similar complexity, though a servlet) is achieved via this unit test [3]

Basically you'll need to:

 

1. Create a Unit Test using Mockito and AEM Mocks

2. In the @Before method

  • Define the testing node structure in a JSON file and load it into the mock text context 
  • Mock the AEM Externalizer service (I don't think AEM Mocks provide this, if they do then you don't have to mock it)
  • Register an instance of YOUR emailService as an OSGI service with the mock OSGi context (youll of course have to make sure any referenced OSGi service as satisfied too -- if this sends you down a rabbit hole, you can just mock your own EmailService and register that mock with the mock OSGi context
  • The other @References should be satisfied by AEM Mocks I think (SlingRepository, ResourceResolverFactory)

2. In your test case, injectAndActivate an instance of your EventListener along w/ any OSGi config properties you want to test it with)

3. Then, using the OSGi mock context get that service back using the interface (you can optionally cast the service to your impl class if you want to discretely test methods that arent on the interface).

4. Then you can test the service.

 

Note that as mentioned on [2] - with JcrMocks "Observation events can be registered but are ignored" - so looks like you'll mock that context when you test onEvent(..).

 

FWIW I think you'll end up spending some time getting it all mocked up/tested -- you may find that you want to refactor your code to be more testable as well.

 

[1] https://wcm.io/testing/aem-mock/

[2] https://sling.apache.org/documentation/development/jcr-mock.html

[3] https://github.com/Adobe-Marketing-Cloud/asset-share-commons/blob/develop/core/src/test/java/com/adobe/aem/commons/assetshare/content/renditions/download/impl/AssetRenditionsDownloadServletTest.java

3 replies

SureshDhulipudi
Community Advisor
Community Advisor
October 29, 2020

@RunWith(PowerMockRunner.class)
@PrepareForTest({UserNotificationListener.class})
public class UserNotificationListenerTest {

@InjectMocks
private UserNotificationListener userNotificationListener;

@Mock
private SlingRepository repository;

@2785667
public void testActivate() throws Exception {

// get details here for activate
Session session = mock(Session.class);
Workspace workspace = mock(Workspace.class);
ObservationManager observationManager = mock(ObservationManager.class);

when(repository.loginService(JcrSessionService.QUERY_SESSION_SERVICE.getService(), null)).thenReturn(session);
when(repository.getDescriptor(Repository.OPTION_OBSERVATION_SUPPORTED)).thenReturn("true");
when(session.getWorkspace()).thenReturn(workspace);
when(workspace.getObservationManager()).thenReturn(observationManager);

userNotificationListener.activate();

verify(observationManager).addEventListener(userNotificationListener, <<<Event.NODE_ADDED>>>, "/<<PATH>>/", true, null, types, true);

}

@2785667
public void testDeactivate() throws Exception {

// get details here for activate
Session session = mock(Session.class);
Workspace workspace = mock(Workspace.class);
ObservationManager observationManager = mock(ObservationManager.class);

when(repository.loginService(JcrSessionService.QUERY_SESSION_SERVICE.getService(), null)).thenReturn(session);
when(repository.getDescriptor(Repository.OPTION_OBSERVATION_SUPPORTED)).thenReturn("true");
when(session.getWorkspace()).thenReturn(workspace);
when(workspace.getObservationManager()).thenReturn(observationManager);

userNotificationListener.deactivate();

verify(<<<>>>>);
}

@2785667
public void testOnEvent() throws Exception {
EventIterator eventIterator = mock(EventIterator.class);
when(eventIterator.hasNext()).thenReturn(true).thenReturn(false);

Event event = mock(Event.class);
when(eventIterator.nextEvent()).thenReturn(event);
<<<<< remaining steps >>>>
}
}

davidjgonzalezzzzAdobe EmployeeAccepted solution
Adobe Employee
October 29, 2020

The cleanest way to unit test this is to simply test is an OSGi service using AEM Mocks [1]  (which are a super-set of Sling Mocks/JCR mocks [2]).

You can see how something (of similar complexity, though a servlet) is achieved via this unit test [3]

Basically you'll need to:

 

1. Create a Unit Test using Mockito and AEM Mocks

2. In the @Before method

  • Define the testing node structure in a JSON file and load it into the mock text context 
  • Mock the AEM Externalizer service (I don't think AEM Mocks provide this, if they do then you don't have to mock it)
  • Register an instance of YOUR emailService as an OSGI service with the mock OSGi context (youll of course have to make sure any referenced OSGi service as satisfied too -- if this sends you down a rabbit hole, you can just mock your own EmailService and register that mock with the mock OSGi context
  • The other @References should be satisfied by AEM Mocks I think (SlingRepository, ResourceResolverFactory)

2. In your test case, injectAndActivate an instance of your EventListener along w/ any OSGi config properties you want to test it with)

3. Then, using the OSGi mock context get that service back using the interface (you can optionally cast the service to your impl class if you want to discretely test methods that arent on the interface).

4. Then you can test the service.

 

Note that as mentioned on [2] - with JcrMocks "Observation events can be registered but are ignored" - so looks like you'll mock that context when you test onEvent(..).

 

FWIW I think you'll end up spending some time getting it all mocked up/tested -- you may find that you want to refactor your code to be more testable as well.

 

[1] https://wcm.io/testing/aem-mock/

[2] https://sling.apache.org/documentation/development/jcr-mock.html

[3] https://github.com/Adobe-Marketing-Cloud/asset-share-commons/blob/develop/core/src/test/java/com/adobe/aem/commons/assetshare/content/renditions/download/impl/AssetRenditionsDownloadServletTest.java

SureshDhulipudi
Community Advisor
Community Advisor
October 30, 2020

you can try like this

 

public class UserNotificationListener implements EventListener {


@RunWith(PowerMockRunner.class)
@PrepareForTest({UserNotificationListener.class})
public class UserNotificationListenerTest {

@InjectMocks
private UserNotificationListener userNotificationListener;

@Mock
private SlingRepository repository;

@2785667
public void testActivate() throws Exception {

// get details here for activate
Session session = mock(Session.class);
Workspace workspace = mock(Workspace.class);
ObservationManager observationManager = mock(ObservationManager.class);

when(repository.loginService(JcrSessionService.QUERY_SESSION_SERVICE.getService(), null)).thenReturn(session);
when(repository.getDescriptor(Repository.OPTION_OBSERVATION_SUPPORTED)).thenReturn("true");
when(session.getWorkspace()).thenReturn(workspace);
when(workspace.getObservationManager()).thenReturn(observationManager);

userNotificationListener.activate();

verify(observationManager).addEventListener(userNotificationListener, <<<Event.NODE_ADDED>>>, "/<<PATH>>/", true, null, types, true);

}

@2785667
public void testDeactivate() throws Exception {

// get details here for activate
Session session = mock(Session.class);
Workspace workspace = mock(Workspace.class);
ObservationManager observationManager = mock(ObservationManager.class);

when(repository.loginService(JcrSessionService.QUERY_SESSION_SERVICE.getService(), null)).thenReturn(session);
when(repository.getDescriptor(Repository.OPTION_OBSERVATION_SUPPORTED)).thenReturn("true");
when(session.getWorkspace()).thenReturn(workspace);
when(workspace.getObservationManager()).thenReturn(observationManager);

userNotificationListener.deactivate();

verify(<<<>>>>);
}

@2785667
public void testOnEvent() throws Exception {
EventIterator eventIterator = mock(EventIterator.class);
when(eventIterator.hasNext()).thenReturn(true).thenReturn(false);

Event event = mock(Event.class);
when(eventIterator.nextEvent()).thenReturn(event);
<<<<< remaining steps >>>>
}
}