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
  • 12459 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?

coder786
coder786Author
February 18, 2020
I am not getting any exception
johnv30691242
New Member
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