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());
}
}
Views
Replies
Total Likes
Can you share details what's not working? Do you get an exception? Is the testcase failing on an assert?
Views
Replies
Total Likes
Views
Replies
Total Likes
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"
}
}
}
}
}
}
Views
Replies
Total Likes
Views
Replies
Total Likes
Views
Replies
Total Likes
Views
Replies
Total Likes
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
Views
Replies
Total Likes
@Kamal_Kishor were you able to resolve this? I am facing similar issue.
Views
Replies
Total Likes
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(); }
Views
Replies
Total Likes
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();
Views
Replies
Total Likes
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
Views
Replies
Total Likes
Views
Likes
Replies
Views
Likes
Replies