How write unit test case for sling servlet which have sql query code | Community
Skip to main content
coder786
February 17, 2020
Solved

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

  • February 17, 2020
  • 3 replies
  • 12455 views

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;

@8220494(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);

@9944223
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";

@1227241
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");
}


@2785667
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());
}

}

Best answer by mvharishb01

For future folks, here is the solution that worked for me

 

Add an inner class like below in your test class

 

public class MockFindResourcesHandlerImpl implements MockFindResourcesHandler {

@Nullable
@Override
public Iterator<Resource> findResources(@NotNull String query, String language) {
// NOTE: In my case I only need one mockedResource,
return Collections.singletonList(mockedResource).iterator();
}
}

How I mocked the resource

// NOTE: Before this line I have loaded the pages to context object through load().json(K,T)
mockedResource
= context.resourceResolver().getResource(ROOT_PATH);

 

Finally, How to use it

// Add below to the BeforeEach method at end (once all context initialization is done)
MockFindQueryResources.addFindResourceHandler(context.resourceResolver(), new MockFindResourcesHandlerImpl());
I Used => ResourceResolverType.RESOURCERESOLVER_MOCK

 

Packages are here:

import org.apache.sling.testing.resourceresolver.MockFindQueryResources;
import org.apache.sling.testing.resourceresolver.MockFindResourcesHandler;



Thank you

- Harish Malineni

 

3 replies

joerghoh
Adobe Employee
Adobe Employee
February 17, 2020

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

joerghoh
Adobe Employee
Adobe Employee
February 29, 2020
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.
September 7, 2021

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


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

johnv30691242
February 11, 2021

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();
}
December 20, 2021

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();

 

mvharishb01
Adobe Employee
mvharishb01Adobe EmployeeAccepted solution
Adobe Employee
November 21, 2024

For future folks, here is the solution that worked for me

 

Add an inner class like below in your test class

 

public class MockFindResourcesHandlerImpl implements MockFindResourcesHandler {

@Nullable
@Override
public Iterator<Resource> findResources(@NotNull String query, String language) {
// NOTE: In my case I only need one mockedResource,
return Collections.singletonList(mockedResource).iterator();
}
}

How I mocked the resource

// NOTE: Before this line I have loaded the pages to context object through load().json(K,T)
mockedResource
= context.resourceResolver().getResource(ROOT_PATH);

 

Finally, How to use it

// Add below to the BeforeEach method at end (once all context initialization is done)
MockFindQueryResources.addFindResourceHandler(context.resourceResolver(), new MockFindResourcesHandlerImpl());
I Used => ResourceResolverType.RESOURCERESOLVER_MOCK

 

Packages are here:

import org.apache.sling.testing.resourceresolver.MockFindQueryResources;
import org.apache.sling.testing.resourceresolver.MockFindResourcesHandler;



Thank you

- Harish Malineni