Hi,
I would like to test the "event_filter" path behavior , specific to if allowed path replication event fired then event handler gets executed vs replication event fired on non-allowed path, event handler does not get executed. This question is more of how I test event handler getting executed only on specific path defined by EVENT_FITLER.
I appreciate any help!
Thanks,
Sri
import com.day.cq.replication.ReplicationAction;
import com.day.cq.replication.ReplicationActionType;
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.api.resource.ResourceResolverFactory;
import org.apache.sling.event.jobs.JobManager;
import org.apache.sling.settings.SlingSettingsService;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.ConfigurationPolicy;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventConstants;
import org.osgi.service.event.EventHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
/**
* Event handler for handling the replication of disclaimer content.
* setting configuration policy to REQUIRE to ensure that the configuration is available only in author instance
* (runmodes) and code executed in author instance not on publish instances.
*
*/
@Component(service = EventHandler.class,
immediate = true,
property = {
EventConstants.EVENT_TOPIC +"=" + ReplicationAction.EVENT_TOPIC,
EventConstants.EVENT_FILTER +"=(paths=/content/siteallowed/*)"
},
configurationPolicy = ConfigurationPolicy.REQUIRE)
public class PublicationEventHandler implements EventHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(PublicationEventHandler.class);
public static final String CONTENT_JOB_TOPIC = "CONTENT-JOB-TOPIC";
@reference
private ResourceResolverFactory resourceResolverFactory;
@reference
private JobManager jobManager;
/**
* Handles the event of clearing the cache whenever a page replication event occurs.
*/
public void handleEvent(Event event) {
try {
ReplicationAction action = ReplicationAction.fromEvent(event);
if (action != null) {
final Map<String, Object> props = new HashMap<>();
props.put("path", action.getPath());
jobManager.addJob(CONTENT_JOB_TOPIC, props);
LOGGER.info("Replication action {} occured on {} ", action.getType().getName(), action.getPath());
}
} catch(Exception e) {
LOGGER.error("Error occurred while handling the event PublicationEventHandler", e);
}
}
}
Solved! Go to Solution.
Topics help categorize Community content and increase your ability to discover relevant content.
Views
Replies
Total Likes
If I understand the OP correct, they want to test the FILTER_PATH behavior, that the filter is invoked correctly when a matching path is provided; and that the code is not invoked when a non-matching path is provided.
Your sample code hardwires that decision; if I change the FILTER_PATH parameter in the production code to something else, the unit test still passes.
You can check this for sample https://github.com/apache/sling-org-apache-sling-testing-osgi-mock/blob/master/core/src/test/java/or...
Hi @sreedobe
Here you can check sample setup Generated by ChatGPT
----------------------------------------------------------------------------------------------------------------------------------------------------------------
To write a JUnit test for the PublicationEventHandler
class in AEM, you can use JUnit 4, Mockito, and AEM Mocks provided by the wcm.io AEM Mocks library. Here's a step-by-step guide to set up and write the test:
Make sure you have the following dependencies in your pom.xml
:
<dependencies>
<!-- JUnit and Mockito -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.11.2</version>
<scope>test</scope>
</dependency>
<!-- AEM Mocks -->
<dependency>
<groupId>io.wcm.testing.aem-mock</groupId>
<artifactId>aem-mock-core</artifactId>
<version>2.8.0</version>
<scope>test</scope>
</dependency>
</dependencies>
Here is the JUnit test class for PublicationEventHandler
:
import com.day.cq.replication.ReplicationAction;
import com.day.cq.replication.ReplicationActionType;
import io.wcm.testing.mock.aem.junit.AemContext;
import org.apache.sling.event.jobs.JobManager;
import org.apache.sling.event.jobs.JobManager;
import org.apache.sling.event.jobs.JobManager;
import org.apache.sling.event.jobs.JobManager;
import org.apache.sling.event.jobs.JobManager;
import org.apache.sling.event.jobs.JobManager;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.osgi.service.event.Event;
import java.util.HashMap;
import java.util.Map;
import static org.mockito.Mockito.*;
public class PublicationEventHandlerTest {
@Rule
public final AemContext context = new AemContext();
@Mock
private JobManager jobManager;
private PublicationEventHandler eventHandler;
@Before
public void setUp() {
MockitoAnnotations.openMocks(this);
eventHandler = new PublicationEventHandler();
context.registerService(JobManager.class, jobManager);
context.registerInjectActivateService(eventHandler);
}
@Test
public void testHandleEvent() {
// Prepare mock event
String path = "/content/siteallowed/test-page";
Map<String, Object> eventProps = new HashMap<>();
eventProps.put("path", path);
Event mockEvent = new Event(ReplicationAction.EVENT_TOPIC, eventProps);
ReplicationAction mockAction = mock(ReplicationAction.class);
when(mockAction.getType()).thenReturn(ReplicationActionType.ACTIVATE);
when(mockAction.getPath()).thenReturn(path);
// Mock static method ReplicationAction.fromEvent
mockStatic(ReplicationAction.class);
when(ReplicationAction.fromEvent(mockEvent)).thenReturn(mockAction);
// Call the handleEvent method
eventHandler.handleEvent(mockEvent);
// Verify that jobManager.addJob was called with the correct parameters
Map<String, Object> jobProps = new HashMap<>();
jobProps.put("path", path);
verify(jobManager, times(1)).addJob(PublicationEventHandler.CONTENT_JOB_TOPIC, jobProps);
// Verify that the static method was called
verifyStatic(ReplicationAction.class, times(1));
ReplicationAction.fromEvent(mockEvent);
}
@Test
public void testHandleEvent_NullAction() {
// Prepare mock event
Event mockEvent = new Event(ReplicationAction.EVENT_TOPIC, new HashMap<>());
// Mock static method ReplicationAction.fromEvent to return null
mockStatic(ReplicationAction.class);
when(ReplicationAction.fromEvent(mockEvent)).thenReturn(null);
// Call the handleEvent method
eventHandler.handleEvent(mockEvent);
// Verify that jobManager.addJob was not called
verify(jobManager, times(0)).addJob(anyString(), anyMap());
// Verify that the static method was called
verifyStatic(ReplicationAction.class, times(1));
ReplicationAction.fromEvent(mockEvent);
}
}
Dependencies: Ensure you have the required dependencies for JUnit, Mockito, and AEM Mocks.
Test Setup:
@Rule
: Sets up the AEM context for testing.@Mock
: Mocks the JobManager
service.setUp()
: Initializes the mocks and registers the services and the event handler.Tests:
testHandleEvent()
: Tests the handleEvent
method for a valid event. It mocks the ReplicationAction.fromEvent
method to return a mock ReplicationAction
and verifies that jobManager.addJob
is called with the correct parameters.testHandleEvent_NullAction()
: Tests the handleEvent
method for a case where ReplicationAction.fromEvent
returns null. It verifies that jobManager.addJob
is not called.Note that mocking static methods with Mockito requires using the mockito-inline
dependency or PowerMockito. In this example, I've used the standard approach. If you need to mock static methods, add the following dependency:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>3.11.2</version>
<scope>test</scope>
</dependency>
And replace the mockStatic
and verifyStatic
methods with appropriate usage as per mockito-inline
documentation.
If I understand the OP correct, they want to test the FILTER_PATH behavior, that the filter is invoked correctly when a matching path is provided; and that the code is not invoked when a non-matching path is provided.
Your sample code hardwires that decision; if I change the FILTER_PATH parameter in the production code to something else, the unit test still passes.
This parameter is used by the runtime (OSGI events) to decide if your code is going to be invoked. That means if you want to test that you have the correct parameters provided to the service you have to have a OSGI runtime running.
That's rather a task for an integration test; unit tests are less suitable, as you would need to startup a OSGI runtime for it. Possible, but I don't know of any unittest framework which does that for you.
On the other hand side: Isn't this a functionality of the framework and you are testing that the framework does the right job?