AEM Servlet junit writing which using querybuilder

bikash_kumar306

18-08-2020

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\"]");

}

}

Accepted Solutions (1)

Accepted Solutions (1)

Vijayalakshmi_S

MVP

19-08-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

	}

}

 

Answers (2)

Answers (2)

kalyan_venkat

19-08-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.