AEM Servlet junit writing which using querybuilder | Community
Skip to main content
Level 2
August 19, 2020
Solved

AEM Servlet junit writing which using querybuilder

  • August 19, 2020
  • 3 replies
  • 11604 views

Hi Have servlet which using querybuilder refrence. When i am writing Junit for that servlet and mocking of querybuilder is not working. I am getting null value for Querybuilder while running the junit .

 

package com.sample.core.servlets;

import static org.apache.sling.api.servlets.ServletResolverConstants.SLING_SERVLET_METHODS;
import static org.apache.sling.api.servlets.ServletResolverConstants.SLING_SERVLET_PATHS;

import java.io.IOException;

 

import java.util.*;
import javax.servlet.Servlet;
import javax.servlet.ServletException;

import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.servlets.HttpConstants;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.json.JSONException;
import org.json.JSONObject;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.day.cq.search.PredicateGroup;
import com.day.cq.search.Query;
import com.day.cq.search.QueryBuilder;
import com.day.cq.search.result.SearchResult;

import javax.jcr.Session;

 

@8220494(
service = { Servlet.class },
property = {
Constants.SERVICE_DESCRIPTION + "= Custom Asset Servlet ",
SLING_SERVLET_PATHS + "=/bin/test/customcreateassetservlet",
SLING_SERVLET_METHODS + "=" + HttpConstants.METHOD_POST
})
public class CustomCreateAssetServlet extends SlingAllMethodsServlet {
private static final long serialVersionUID = 4480344238141080952L;
private static final Logger log = LoggerFactory.getLogger(CustomCreateAssetServlet.class);

protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
try {
String assetsValue =request.getParameter("assetList");
log.info("assetsValue:"+assetsValue);
List<String> duplicateassetList = new ArrayList<String>();

List<String> assetList = new ArrayList<String>();
int length = 0;

String assets[] =assetsValue.split(",");

if(assets !=null && assets.length>0) {
for(int i=0; i<assets.length; i++) {
String assetName =assets[i];
assetList.add(assetName.substring(0, assetName.lastIndexOf(".")));
}
}

ResourceResolver resourceResolver = request.getResourceResolver();
QueryBuilder queryBuilder = resourceResolver.adaptTo(QueryBuilder.class);
HashMap<String, String> queryMap = new HashMap<String, String>();
queryMap.put("type", "dam:Asset");
queryMap.put("property", "@jcr:content/metadata/dam:scene7Name");
if(assetList !=null && assetList.size()>0) {
for(int i=0;i<assetList.size(); i++) {
queryMap.put("property."+i+1+"_value", assetList.get(i));
}
}

queryMap.put("orderby", "path");
queryMap.put("p.limit", "-1");
PredicateGroup predicate = PredicateGroup.create(queryMap);
Query query = queryBuilder.createQuery(predicate, resourceResolver.adaptTo(Session.class));
SearchResult searchResults = query.getResult();
length = searchResults.getHits().size();
for (int i = 0; i < length; i++) {
Resource resource = searchResults.getHits().get(i).getResource();
String resourcePath = resource.getPath();
duplicateassetList.add(resourcePath);
log.info("resourcePath:"+resourcePath);
}

JSONObject jsonobject = new JSONObject();
jsonobject.put("duplicateAssets", duplicateassetList);
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
response.getWriter().write(jsonobject.toString());


}catch (JSONException exceptionObject) {
log.error("Could not formulate JSON response");
response.setStatus(SlingHttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.getWriter().write("ERROR");
} catch (Exception e) {
log.error("Exception Occured" + e.getMessage());
response.setStatus(SlingHttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.getWriter().write("ERROR");
}
}

}

 

 

Junit for above Class:

 

ckage com.sample.core.servlets;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.jcr.Session;
import javax.servlet.http.HttpServletResponse;

import org.apache.sling.api.resource.ResourceResolver;
import org.json.JSONObject;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;

import com.day.cq.search.PredicateGroup;
import com.day.cq.search.Query;
import com.day.cq.search.QueryBuilder;
import com.day.cq.search.result.Hit;
import com.day.cq.search.result.SearchResult;

import io.wcm.testing.mock.aem.junit5.AemContext;
import io.wcm.testing.mock.aem.junit5.AemContextExtension;

@ExtendWith(AemContextExtension.class)
@15595559("Create Asset Servlet Test Cases")
public class CustomCreateAssetServletTest {

private final AemContext context = new AemContext();

@InjectMocks
CustomCreateAssetServlet customCreateAssetServlet = new CustomCreateAssetServlet();

@Mock
private ResourceResolver resourceResolver;

@Mock
private QueryBuilder queryBuilder;

@Mock
private PredicateGroup predicate;

@Mock
private Session session ;

@Mock
private Query query;

String assetsValue ="homelogo.png,Sample_Logo_portal.png,";

HashMap<String, String> queryMap;

JSONObject jsonObject = new JSONObject();


@BeforeEach
void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
queryMap = new HashMap<String, String>();
queryMap.put("type", "dam:Asset");
queryMap.put("property", "@jcr:content/metadata/dam:scene7Name");
queryMap.put("property.1_value", "homelogo");
queryMap.put("orderby", "path");
queryMap.put("p.limit", "-1");
}

@2785667
@15595559("Do Post with No Param")
void test_with_no_param() throws Exception {
Map<String, Object> parameterMap = new HashMap<>();
parameterMap.put("", "");
context.request().setParameterMap(parameterMap);
customCreateAssetServlet.doPost(context.request(), context.response());
assertEquals(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, context.response().getStatus());
}

@2785667
@15595559("Do Post with Blank Path Param")
void test_with_blank_path_param() throws Exception {
Map<String, Object> parameterMap = new HashMap<>();
parameterMap.put("assetList", "");
context.request().setParameterMap(parameterMap);
customCreateAssetServlet.doPost(context.request(), context.response());
assertEquals(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, context.response().getStatus());
}

@2785667
@15595559("Do Post with Asset List Param With All Attributes")
void test_with_asset_list_all_param() throws Exception {
Map<String, Object> parameterMap = new HashMap<>();
parameterMap.put("assetList", assetsValue);
context.request().setParameterMap(parameterMap);
when(resourceResolver.adaptTo(QueryBuilder.class)).thenReturn(queryBuilder);
when(resourceResolver.adaptTo(Session.class)).thenReturn(session);

// Session session = mock(Session.class);
// Query query = mock(Query.class);
when(queryBuilder.createQuery(Mockito.any(PredicateGroup.class), Mockito.eq(session))).thenReturn(query);
List<Hit> listHits = new ArrayList<>();
Hit hit = mock(Hit.class);
listHits.add(hit);
SearchResult searchResults = mock(SearchResult.class);


when(query.getResult()).thenReturn(searchResults);
when(searchResults.getHits()).thenReturn(listHits);
when(hit.getPath()).thenReturn("/content/dam/home/logo/homelogo.png");
customCreateAssetServlet.doPost(context.request(), context.response());
// JSONObject responseObject = new JSONObject(context.response());
// JSONObject assetsReponseJSON = new JSONObject(responseObject.getString("outputAsString").toString());
assertEquals(HttpServletResponse.SC_OK, context.response().getStatus());
// assertEquals(responseObject.get("duplicateAssets").toString(),"[\"/content/dam/home/logo/homelogo.png\"]");

}

}

Best answer by Vijayalakshmi_S

Hi @bikash_kumar306,

As QueryBuilder can be adapted from ResourceResolver object, we can make use of registerAdapter method from AemContext as below

 

 

@Mock // This is from org.mockito.Mock; private QueryBuilder queryBuilder; private final AemContext aemContext = new AemContext(ResourceResolverType.JCR_MOCK); aemContext.registerAdapter(ResourceResolver.class, QueryBuilder.class, queryBuilder);

 

 

Sample Test class structure for reference:

 

import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.lenient; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.jcr.Session; import javax.servlet.ServletException; import javax.servlet.http.HttpServletResponse; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceResolver; 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.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import com.day.cq.search.PredicateGroup; import com.day.cq.search.Query; import com.day.cq.search.QueryBuilder; import com.day.cq.search.result.SearchResult; import io.wcm.testing.mock.aem.junit5.AemContext; import io.wcm.testing.mock.aem.junit5.AemContextExtension; @ExtendWith({ AemContextExtension.class, MockitoExtension.class }) class CustomCreateAssetServletTest { private final AemContext aemContext = new AemContext(ResourceResolverType.JCR_MOCK); @Mock private QueryBuilder queryBuilder; @Mock private Query query; @Mock private SearchResult searchResult; private List<Resource> queryResults = new ArrayList<>(); // Populate this collection with actual results/test assets, to be checked in response JSON String @BeforeEach void setUp() throws Exception { /* Query Builder is adapted from Resource Resolver */ aemContext.registerAdapter(ResourceResolver.class, QueryBuilder.class, queryBuilder); lenient().when(queryBuilder.createQuery(any(PredicateGroup.class), any(Session.class))).thenReturn(query); lenient().when(query.getResult()).thenReturn(searchResult); lenient().when(searchResult.getResources()).thenReturn(queryResults.iterator()); // test content/result is returned, can add further dummy implementation based on the actual code statements } @Test void testDoPostSlingHttpServletRequestSlingHttpServletResponse() throws ServletException, IOException { /* Request from Context */ MockSlingHttpServletRequest mockRequest = aemContext.request(); /* Response from Context */ MockSlingHttpServletResponse mockResponse = aemContext.response(); /* Instantiate Servlet under test */ CustomCreateAssetServlet servletToTest = new CustomCreateAssetServlet(); /* Invoke method under test */ servletToTest.doPost(mockRequest, mockResponse); /* Assert Response status */ assertEquals(HttpServletResponse.SC_OK, mockResponse.getStatus()); /* Assert Response String */ assertTrue(mockResponse.getOutputAsString().contains("")); // Amend this assertion per the way you set the test content } }

 

3 replies

Level 3
August 19, 2020

Hi @bikash_kumar306 

 

Have you tried not mocking the resourceResolver because AEM context object provides you resourceResolver and it should adaptTo queryBuilder API by default. Try to debug with a break point in your servlet class and make sure resourceResolver is injected correctly.

Level 2
August 19, 2020
Hi Kalyan,
Nikhil-Kumar
Community Advisor
Community Advisor
August 19, 2020

@bikash_kumar306 
Try using PowerMockito or Prepare QueryBuilder class for mock.
long back using mockStatic(QueryBuilder.class) worked for me.


Vijayalakshmi_S
Vijayalakshmi_SAccepted solution
Level 10
August 19, 2020

Hi @bikash_kumar306,

As QueryBuilder can be adapted from ResourceResolver object, we can make use of registerAdapter method from AemContext as below

 

 

@Mock // This is from org.mockito.Mock; private QueryBuilder queryBuilder; private final AemContext aemContext = new AemContext(ResourceResolverType.JCR_MOCK); aemContext.registerAdapter(ResourceResolver.class, QueryBuilder.class, queryBuilder);

 

 

Sample Test class structure for reference:

 

import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.lenient; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.jcr.Session; import javax.servlet.ServletException; import javax.servlet.http.HttpServletResponse; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceResolver; 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.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import com.day.cq.search.PredicateGroup; import com.day.cq.search.Query; import com.day.cq.search.QueryBuilder; import com.day.cq.search.result.SearchResult; import io.wcm.testing.mock.aem.junit5.AemContext; import io.wcm.testing.mock.aem.junit5.AemContextExtension; @ExtendWith({ AemContextExtension.class, MockitoExtension.class }) class CustomCreateAssetServletTest { private final AemContext aemContext = new AemContext(ResourceResolverType.JCR_MOCK); @Mock private QueryBuilder queryBuilder; @Mock private Query query; @Mock private SearchResult searchResult; private List<Resource> queryResults = new ArrayList<>(); // Populate this collection with actual results/test assets, to be checked in response JSON String @BeforeEach void setUp() throws Exception { /* Query Builder is adapted from Resource Resolver */ aemContext.registerAdapter(ResourceResolver.class, QueryBuilder.class, queryBuilder); lenient().when(queryBuilder.createQuery(any(PredicateGroup.class), any(Session.class))).thenReturn(query); lenient().when(query.getResult()).thenReturn(searchResult); lenient().when(searchResult.getResources()).thenReturn(queryResults.iterator()); // test content/result is returned, can add further dummy implementation based on the actual code statements } @Test void testDoPostSlingHttpServletRequestSlingHttpServletResponse() throws ServletException, IOException { /* Request from Context */ MockSlingHttpServletRequest mockRequest = aemContext.request(); /* Response from Context */ MockSlingHttpServletResponse mockResponse = aemContext.response(); /* Instantiate Servlet under test */ CustomCreateAssetServlet servletToTest = new CustomCreateAssetServlet(); /* Invoke method under test */ servletToTest.doPost(mockRequest, mockResponse); /* Assert Response status */ assertEquals(HttpServletResponse.SC_OK, mockResponse.getStatus()); /* Assert Response String */ assertTrue(mockResponse.getOutputAsString().contains("")); // Amend this assertion per the way you set the test content } }

 

Level 2
August 20, 2020
Hi Vijayalakshmi_S, Thanks it's worked.