I have been updating out code base with unit tests and they have some Sling servlets that are obtaining the service user based ResourceResolver for extra work and making calls to other services. The issue I'm having is that the servlet uses @reference ResourceResolverFactory resourceResolverFactory to obtain an instance of the factory. In my tests, I have tried AemContext.registerService(ResourceResolverFactory.class, resourceResolverInstance) to attempt to set the mocked factory. The servlet is not resolving the service so I am unable to perform a proper test.
I am using the mockito-core 3.3.3 , org.apache.sling.testing.osgi-mock.junit5 3.1.2, io.wcm.testing.aem-mock.junit5 3.0.2, mockito-junit-jupiter 3.3.3 dependencies. Many of the on line samples don't work with these versions because packaging and classes have changed.
Help with resources and what I need to do in order to get the @reference annotation to include the testing instance of the ResourceResolverFactory would be fantastic.
Solved! Go to Solution.
Views
Replies
Total Likes
Hi @RobertHarper,
For the snippet that you have shared now, here is the Test class, you can use this as is and check if it works now.
Changes done (on top of what you shared)
package com.mysite.core.servlets; import java.io.IOException; import javax.servlet.ServletException; import org.apache.sling.api.resource.ResourceResolverFactory; import org.apache.sling.testing.mock.sling.ResourceResolverType; import org.apache.sling.testing.mock.sling.servlet.MockSlingHttpServletRequest; import org.apache.sling.testing.mock.sling.servlet.MockSlingHttpServletResponse; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import io.wcm.testing.mock.aem.junit5.AemContext; import io.wcm.testing.mock.aem.junit5.AemContextExtension; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import static org.junit.jupiter.api.Assertions.assertEquals; @ExtendWith({AemContextExtension.class, MockitoExtension.class}) class SimpleServletTest { @Mock private ResourceResolverFactory resourceResolverFactory; private AemContext context = new AemContext(ResourceResolverType.RESOURCERESOLVER_MOCK); @InjectMocks private SimpleServlet fixture = new SimpleServlet(); @Test void doGet() throws ServletException, IOException { context.build().resource("/content/test", "jcr:title", "resource title").commit(); context.currentResource("/content/test"); MockSlingHttpServletRequest request = context.request(); MockSlingHttpServletResponse response = context.response(); fixture.doGet(request, response); assertEquals("Title = resource title", response.getOutputAsString()); } }
Once when you see the above working, you can try the below.
For creating ResourceResolver out of this mocked ResourceResolverFactory, we need to introduce when and thenReturn
Map<String, Object> map = new HashMap<>(); map.put(ResourceResolverFactory.SUBSERVICE, "demoproject-service"); /* Getting Resolver from current AemContext */ ResourceResolver resourceResolver = context.request().getResourceResolver(); /*Using the resolver from previous step for thenReturn */ when(rescResolverFactory.getServiceResourceResolver(map)).thenReturn(resourceResolver);
Update : (Corrected the typo on variable name of mocked ResourceResolverFactory)
when(resourceResolverFactory.getServiceResourceResolver(map)).thenReturn(resourceResolver);
The mocked ResourceResolverFactory is not used in the test, so you should be able to remove it.
Otherwise: +1
That was okay. The big thing was go see how to get the reference to resolve while testing. Once that worked, more code was written for the real test. If the ResourceResolverFactory had been omitted from the example, nothing would have been gained.
Above is returning below error
java.lang.IllegalStateException: Resource resolver is already closed.
at org.apache.sling.resourceresolver.impl.ResourceResolverImpl.checkClosed(ResourceResolverImpl.java:186)
at org.apache.sling.resourceresolver.impl.ResourceResolverImpl.adaptTo(ResourceResolverImpl.java:807)
at org.apache.sling.testing.mock.sling.context.SlingContextImpl.tearDown(SlingContextImpl.java:225)
at io.wcm.testing.mock.aem.context.AemContextImpl.tearDown(AemContextImpl.java:105)
at io.wcm.testing.mock.aem.junit5.AemContext.tearDownContext(AemContext.java:107)
at io.wcm.testing.mock.aem.junit5.AemContextExtension.lambda$afterEach$3(AemContextExtension.java:152)
at io.wcm.testing.mock.aem.junit5.AemContextExtension.applyAemContext(AemContextExtension.java:180)
at io.wcm.testing.mock.aem.junit5.AemContextExtension.afterEach(AemContextExtension.java:147)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeAfterEachCallbacks$12(TestMethodTestDescriptor.java:233)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeAllAfterMethodsOrCallbacks$14(TestMethodTestDescriptor.java:245)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeAllAfterMethodsOrCallbacks(TestMethodTestDescriptor.java:243)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeAfterEachCallbacks(TestMethodTestDescriptor.java:232)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:133)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:229)
at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:197)
at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:211)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:191)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Process finished with exit code 255
Here is servlet, test class
@Component(
service = Servlet.class,
name = "Reform Servlet",
property = {
"sling.servlet.paths=" + "/bin/reform-message",
"sling.servlet.methods=" + HttpConstants.METHOD_GET
}
)
public class ReformServlet extends SlingAllMethodsServlet implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger log = LoggerFactory.getLogger(ReformServlet.class);
private ConfigurationAdmin configAdmin;
@Reference
private ResourceResolverFactory rFactory;
protected void doGet(final SlingHttpServletRequest request, final SlingHttpServletResponse response)
throws ServletException,IOException
{
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
try
{
log.info("ReformServlet.doGet");
out.write( getMessage());
}
catch (Exception ex)
{
{
response.setStatus(500);
out.write("doGet - Message ReformServlet");
}
}
}
private String getMessage()
{
//servlet returns JSON string
String jsonData = "{}";
try(ResourceResolver rSolver = ResourceResolverUtil.getResourceResolver(rFactory))
{
String jcrPath = getProperty("jcrPath");
String datataPath = getProperty("dataPath");
Resource mfDataNode = rSolver.getResource(jcrPath+ "/" + dataPath);
if(mfDataNode != null){
jsonData = mfDataNode.getValueMap().get("messageData",String.class);
}
else
{
log.error("data doesnot exist");
}
}
catch (Exception e)
{
log.error("caught exception", e);
}
return jsonData;
}
protected String getProperty(String key)
throws Exception
{
String property = null;
try
{
Configuration config = (Configuration) configAdmin
.getConfiguration(Constants.ConfigProperties.OSGI_CONFIG_NAME);
Dictionary props = config.getProperties();
property = (String)props.get(key);
}
catch(Exception e)
{
log.error("caught exception getting property {}", key);
throw(e);
}
return property;
}
}
@ExtendWith({ AemContextExtension.class, MockitoExtension.class })
class ReformServletTest {
private final AemContext context = new AemContext(ResourceResolverType.JCR_MOCK);
@Mock
private ConfigurationAdmin configAdmin;
@Mock
private ResourceResolverFactory resolverFactory;
@InjectMocks
private ReformServlet fixture = new ReformServlet();
@BeforeEach
void setUp() throws IOException {
MockitoAnnotations.initMocks(this);
context.create().resource("/content/test", ImmutableMap.<String, Object>builder()
.put("jcr:title", "test page")
.build());
context.create().resource("/content/test/reform-cache", ImmutableMap.<String, Object>builder()
.put("jcr:title", "reform cache")
.put("messageData", "{\"globalMessage\":\"some message\"}")
.build());
}
void doGet() throws ServletException, IOException, LoginException {
context.currentResource("/content/test");
MockSlingHttpServletRequest request = context.request();
MockSlingHttpServletResponse response = context.response();
Configuration configurationMock = Mockito.mock(Configuration.class);
Mockito.when(configAdmin.getConfiguration(Mockito.anyString())).thenReturn(configurationMock);
Mockito.when(configurationMock.getProperties()).thenReturn(new Hashtable<String, Object>(){{
put("jcrPath", "/content/test");
put("dataPath", "reform-cache");
}});
Mockito.when(resolverFactory.getServiceResourceResolver(Mockito.anyMap())).thenReturn(context.request().getResourceResolver());
fixture.doGet(request, response);
assertEquals(response.getOutputAsString(), "{\"globalMessage\":\"some message\"}");
}
}
Views
Replies
Total Likes