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;
@component(
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)
@displayname("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");
}
@test
@displayname("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());
}
@test
@displayname("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());
}
@test
@displayname("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\"]");
}
}
Solved! Go to Solution.
Views
Replies
Total Likes
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
}
}
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.
Views
Replies
Total Likes
Views
Replies
Total Likes
Views
Replies
Total Likes
@bikash_kumar306
Try using PowerMockito or Prepare QueryBuilder class for mock.
long back using mockStatic(QueryBuilder.class) worked for me.
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
}
}
Views
Replies
Total Likes
Vijayalakshmi_S - Thank you much for the code snippet. It helped me to solve querybuilder mock issue
Views
Replies
Total Likes
Vijayalakshmi_S - The below line did the magic.
aemContext.registerAdapter(ResourceResolver.class, QueryBuilder.class, queryBuilder);
I was getting queryBuilder as null and I spent almost a day to debug this issue. I double check all mock and everything but issue did not solve. After adding this line solved the issue. How do you know this? Is there any official documention ? I tried to see in https://wcm.io/testing/aem-mock/usage.html but there is method found "registerAdapter".
Could you please tell me where and how do we come to all these api details ?
Views
Replies
Total Likes
Views
Likes
Replies
Views
Likes
Replies