Expand my Community achievements bar.

Guidelines for the Responsible Use of Generative AI in the Experience Cloud Community.

How write unit test case for sling servlet which have sql query code

Avatar

Level 1

Hi, 

How I can write unit test case for sling servlet which have sql query code. I have tried to write unit test but that is not working kindly look below is the sling servlet code and unit test code share what's wrong I am doing

# Servlet


import java.io.IOException;
import java.util.Iterator;
import java.util.Objects;

import javax.servlet.Servlet;

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.JSONArray;
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.wcm.api.Page;

@component(service = Servlet.class, property = { Constants.SERVICE_DESCRIPTION + "= Global Search Servlet",
"sling.servlet.methods=" + HttpConstants.METHOD_GET, "sling.servlet.paths=" + "/bin/mysite/globalsearch" })
public class GlobalSearchServlet extends SlingAllMethodsServlet {

private static final long serialVersionUID = 1L;
private static final transient Logger LOG = LoggerFactory.getLogger(GlobalSearchServlet.class);

@Override
public void doGet(SlingHttpServletRequest req, SlingHttpServletResponse res) {
ResourceResolver resourceResolver = req.getResourceResolver();
String keyword = null;
res.setContentType("application/json");
res.setCharacterEncoding("UTF-8");
JSONArray jsonArray = new JSONArray();
try {
keyword = req.getParameter("q");
if (Objects.nonNull(keyword)) {
String query = "select * from [cq:Page] as a where contains(*, '"+keyword+"') and isdescendantnode(a, '/content/mysite')";
Iterator<Resource> results = resourceResolver.findResources(query, "sql");
while (results.hasNext()) {
JSONObject object = new JSONObject();
Resource resource = results.next();
Page page =resource.adaptTo(Page.class);
object.put("path", page.getPath());
object.put("title", page.getTitle());
jsonArray.put(object);
}
} else {
LOG.info("Query Parameter is missing in request.");
}
res.getWriter().print(jsonArray);
} catch (IOException | JSONException ioe) {
LOG.error("Error occurred. Error ", ioe);
}
}
}

 

 

#Unit Test

 


import static org.junit.Assert.assertEquals;
import java.io.IOException;
import javax.servlet.ServletException;
import org.apache.sling.commons.json.JSONException;
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.Before;
import org.junit.Rule;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.wcm.testing.mock.aem.junit.AemContext;

public class GlobalSearchServletTest {

private static final String MOCK_JSON = "/globalsearch/globalsearch.json";

@Deleted Account
public final AemContext context = new AemContext(ResourceResolverType.JCR_OAK);

static final Logger LOG = LoggerFactory.getLogger(GlobalSearchServletTest.class);


@Before
public void setup() {
context.load().json(MOCK_JSON, "/content");
}


@test
public void testDoGet() throws ServletException, IOException, JSONException {
GlobalSearchServlet servlet = new GlobalSearchServlet();

context.currentPage(context.pageManager().getPage("/content/mysite"));
context.currentResource(context.resourceResolver().getResource("/content/mysite"));
context.requestPathInfo().setResourcePath("/content/mysite");

MockSlingHttpServletRequest request = context.request();
request.setQueryString("q=the");

MockSlingHttpServletResponse reponse = context.response();

servlet.doGet(request, reponse);

System.out.println("RESPONSE=="+context.response().getOutputAsString());


LOG.info("output = {}", context.response().getOutputAsString());
assertEquals("[{\"message\":\"0 results found\",\"status\":false}]",context.response().getOutputAsString());
}

}

10 Replies

Avatar

Employee Advisor

Can you share details what's not working? Do you get an exception? Is the testcase failing on an assert?

Avatar

Level 1

I am not getting any exception But while running the unit test case I am not getting any response or to be more precise not getting any result from query execution

String query = "select * from [cq:Page] as a where contains(*, '"+keyword+"') and isdescendantnode(a, '/content/mysite')";
Iterator<Resource> results = resourceResolver.findResources(query, "sql");

 

Below is the page json. Can you share what's wrong I am doing here or it not possible? 

 

{
"jcr:content": "nt:unstructured",
"mysite": {
"jcr:primaryType": "cq:Page",
"jcr:content": {
"jcr:primaryType": "cq:PageContent",
"jcr:title": "the mysite page"
},
"dashboard": {
"jcr:primaryType": "cq:Page",
"jcr:content": {
"jcr:primaryType": "cq:PageContent",
"jcr:title": "the dashboard page"
},
"homepage": {
"jcr:primaryType": "cq:Page",
"jcr:content": {
"jcr:primaryType": "cq:PageContent",
"jcr:title": "the home page"
},
"userpage": {
"jcr:primaryType": "cq:Page",
"jcr:content": {
"jcr:primaryType": "cq:PageContent",
"jcr:title": "the user page"
}
},
"productpage": {
"jcr:primaryType": "cq:Page",
"jcr:content": {
"jcr:primaryType": "cq:PageContent",
"jcr:title": "the product page"
}
}
}
}
}
}

 

Avatar

Employee Advisor
Both the testcase and the test data look reasonable, and i don't understand what could be wrong here. Can you execute that testcase in an IDE, set a breakpoint and inspect in the debugger the loaded repository structure?

Avatar

Level 1
Can you advice where i can put logger to check what the content repository loaded?

Avatar

Employee Advisor
In eclipse when I set a breakpoint in the testcase and I can drill down into all available objects in the current scope, and if you are going down in the AemContext object you can find the content of the repo. A bit cumbersome, but works. I am not aware of any convenience method to dump the content of the repository of the AemContext.

Avatar

Level 9

I have the same issue -

while I can see the resource created with context.load().json(inputStream, "/content");

 

Issue is when executing Iterator<Resource> resources = resolver.findResources(query, "JCR-SQL2")
I am not getting the resource in iterator.

@Jörg_Hoh

Avatar

Level 1

@Kamal_Kishor were you able to resolve this? I am facing similar issue.

Avatar

Level 1

I've found that when using JCR_OAK and the findResources() method, it works once you've committed the loaded data from the JSON:

@Before
public void setup() {
    context.load().json(MOCK_JSON, "/content");
    context.resourceResolver().commit();
}

Avatar

Level 1

1. Create AemContext object by setting the ResourceResolverType to JCR_OAK

public AemContext context = new AemContext(ResourceResolverType.JCR_OAK);

2. On loading the JSON, commit the resource resolver

context.load().json(PAGE_JSON, PAGE);
context.resourceResolver().commit();