hi guys i need help from you, i created chillist servlet for reading properties from /content it returns a JSONArray of the node's child node paths and properties.
so plz help for unit testing. i need unit testing script for this code, this my code
package com.aem.community.core.servlets;
import java.io.IOException;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.servlet.ServletException;
import org.apache.felix.scr.annotations.Service;
import org.apache.felix.scr.annotations.sling.SlingServlet;
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.SlingAllMethodsServlet;
import org.apache.sling.commons.json.JSONArray;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.JSONObject;
import org.apache.sling.commons.json.jcr.JsonJcrNode;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Component(enabled = true, immediate = true)
@Service(ChildList.class)
@SlingServlet(resourceTypes="sling/servlet/default",selectors="childlist",methods="GET",extensions="json",metatype=true)
public class ChildList extends SlingAllMethodsServlet {
protected final Logger loger = LoggerFactory.getLogger(ChildList.class);
private static final long serialVersionUID = 9176255033916949528L;
private JSONArray array;
@Override
public void doGet(final SlingHttpServletRequest request, final SlingHttpServletResponse response)
throws ServletException, IOException {
try{
ResourceResolver resolver = request.getResourceResolver();
Resource resource = resolver.getResource(request.getRequestPathInfo().getResourcePath());
Node node = null;
if (resource != null) {
node = resource.adaptTo(Node.class);
}
if (node == null){
throw new RepositoryException();
}
NodeIterator it = node.getNodes();
array = new JSONArray();
while (it.hasNext()) {
Node child = it.nextNode();
if (loger.isDebugEnabled()){
loger.debug("resource......."+child.getPath());
}
JSONObject obj = new JsonJcrNode(child);
array.put(obj);
response.setContentType("application/json");
response.getOutputStream().print(array.toString());
}
}
catch(RepositoryException e) {
throw new ServletException("404 HTTP ERROR Page Not Found", e);
}
catch(JSONException e)
{
loger.error("Could not formulate JSON response");
throw new ServletException("Error", e);
}
}
}
Jörg_Hoh
Employee
Jörg_Hoh
Employee
02-05-2018
Today I rewrote unittests for the whole day ... so while I just was on it, I wrote them for this question, too.
You can find the complete code at https://github.com/joerghoh/cqdump/tree/master/unittests
Clone it and then run it (the usual "mvn clean install").
The relevant bits and pieces:
I used the AEM Mocks from wcm.io, which work pretty good for usecases like yours.
HTH,
Jörg
BrianKasingli
MVP
BrianKasingli
MVP
21-12-2019
Hello @naveent23995593,
A more modern way to write Sling Servlets will be to write it with the OSGI DS 1.4 (R7) annotations. For instance, a Sling Servlet registered by resource types can utilise this annotation @SlingServletResourceType.
Writing unit tests for @SlingServletResourceType is very simple. Utilising the AEM Mocks JUnit library, First, you would need to instantiate the Sling Servlet object. Thereafter, you would need to pass in the Sling request and response (wcm.testing.io) mock objects to the doGet() method. Finally, you can start your assertion tests.
It makes more sense in this example (code snippet examples) - https://sourcedcode.com/aem-sling-servlet-osgi-r7-by-resource-type-unit-test-junit-4-with-examples
Jörg_Hoh
Employee
Jörg_Hoh
Employee
14-05-2018
Hi,
I am sorry, I got lost somewhere in this thread. For me it looks like that you are stuck with writing unit tests in an area which is not directly related to AEM anymore. I hope that I was able to provide you some starting point to write tests, but I am not able to support you writing unittests for your business logic. Although I am happy to help if there are questions how you can unit test (or mock) certain aspects of AEM.
kind regards,
Jörg
naveent23995593
naveent23995593
14-05-2018
public class ChildListJsonTest
{
@Rule
public AemContext context = new AemContext(ResourceResolverType.JCR_MOCK);
static final Logger LOG = LoggerFactory.getLogger(ChildListJsonTest.class);
@Before
public void setup() {
context.registerService(ImplementationPicker.class, new ResourceTypeBasedResourcePicker());
context.addModelsForPackage("com.aem.community.core.servlets");
context.load().json(getClass().getResourceAsStream(getClass().getSimpleName() + ".json"),"/content");
}
@Test
public void testContentVersion() throws ServletException, IOException, JSONException {
ChildList servlet =new ChildList();
BundleContext bundleContext=MockOsgi.newBundleContext();
MockSling.setAdapterManagerBundleContext(bundleContext);
//bundleContext.registerService(myAdapterFactory);
//MockOsgi.injectServices(servlet, bundleContext);
context.currentPage(context.pageManager().getPage("/content")); // getting path /content
context.currentResource(context.resourceResolver().getResource("/content")); // getting resource path /content
context.requestPathInfo().setResourcePath("/content");
servlet.doGet(context.request(), context.response());
assertTrue("Incorrect content type received","application/json".equals(context.response().getContentType())); //getting contentType application/json
LOG.info("output = {}", context.response().getOutputAsString());
JSONArray output = new JSONArray(context.response().getOutputAsString());
System.out.println("output"+output.length());
assertEquals("JSON Objects in array",25,output.length());
}
}
how to solve this issue,i reffered BundleContextService api but didn't get any clarity about that
naveent23995593
naveent23995593
10-05-2018
where we write this logic, how to write can u helpme
Create an HTML filtering filter as part of the publish tools bundle.
The filter can be disabled by the bundle configuration: enable.htmlfilter.filter {Boolean}
The filter must be disabled by default.
This filter will get involved in HTTP responses with a content-type of text/html.
The user will be able to "filter" the outputted HTML by optionally passing a querySelector (see https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector) in the request, and also, by passing an "extraction" method.
For example, let
/content/mysite/aboutus.html
output
<div class="about-us" title="Who we are">
<h1>About Us</h1>
<p>Find out who we are</p>
We are the best.
</div>
In such example, the following htmlfilter parameters
/content/mysite/aboutus.html?htmlfilter={
"filters": [{
"selector": "h1",
"extract": "TEXT"
}]
}
Would replace the current response output with:
About Us
Usagection methods are supported
TEXTCONTENT
The following extra
OWNTEXT
INNERHTML
OUTERHTML
@attribute
The JSOUP library will be used to internal query and extract desired the HTML parts. (See https://jsoup.org/)
(Note that JSOUP is already provided in AEM when rapid-commons is installed)
In the example HTML page above and the following htmlfilter parameters
/content/mysite/aboutus.html?htmlfilter={
"filters": [{
"selector": ".about-us",
"extract": "..."
}]
}
If the extract property is set to TEXT the output would be
About UsFind out who we are We are the best.
If the `extract` property is set to `OWNTEXT` the output would be
We are the best.
If the `extract` property is set to `INNERHTML` the output would be
<h1>About Us</h1>
<p>Find out who we are</p>
We are the best.
If the `extract` property is set to `OUTERHTML` the output would be
<div class="about-us" title="Who we are">
<h1>About Us</h1>
<p>Find out who we are</p>
We are the best.
</div>
If the `extract` property is set to `@title` the output would be
Who we are
Multiple `filters` may also be passed. In such case a `glue` property may also be passed to the filter
/content/rapid/mysite/aboutus.html?htmlfilter={{{ }}
"filters": [
{
"selector": "h1",
"extract": "TEXT"
},
{
"selector": "p",
"extract": "TEXT"
}
],
"glue": ": "
}
Outputs
About Us: Find out who we are
Note that, the following htmlfilter parameters would have produced the same output for that page
/content/rapid/mysite/aboutus.html?htmlfilter={
"filters": [{
"selector": "h1, p",
"extract": "TEXT"
}],
"glue": ": "
}
Outputs
About Us: Find out who we are
The advantage in the former format is that the user has the opportunity to pass a different `extract` value for each filter.
In the client does not pass a `glue` property or passed a `glue` property with a value `null`, the htmlfilter must use the default glue defined in the bundle setting:
htmlfilter.default.glue{String} = <i class="htmlfilter-glue"></i>
Thus such request:
/content/rapid/mysite/aboutus.html?htmlfilter={
"filters": [{
"selector": "h1, p",
"extract": "TEXT"
}]
}
Would output
About Us<i class="htmlfilter-glue"></i>Find out who we are
And such request:
/content/rapid/mysite/aboutus.html?htmlfilter={
"filters": [
{
"selector": "h1",
"extract": "TEXT"
},
{
"selector": "h2",
"extract": "TEXT"
},
{
"selector": "p",
"extract": "TEXT"
}
]
}
Would output
About Us<i class="htmlfilter-glue"></i><i class="htmlfilter-glue"></i>Find out who we are
Parameters
The htmlfilter can take parameters in 2 different formats (but only 1 at a time):
As a request parameter (e.g. `request.getParameter()` provided either in the URL query string or POST form data
As a request header
Which one the filter is currently monitoring is is determined in the bundle configuration
htmlfilter.input {String} = parameter htmlfilter
The value of this configuration is simply a space delimited String in which the first part can either be `parameter` or `header` and the second part can be an arbitrary, space-less key.
For example, `parameter htmlfilter`, which is the default, means that the filter will get its input parameter in the request parameter named `htmlfilter`. (e.g. `request.getParamter("htmlfilter")`)
Had the value of this configuration be
htmlfilter.input{String}= header x-rpt-htmlfilter
It would mean that the filter will get its input parameter in the request header named `x-rpt-htmlfilter`. (e.g. `request.getHeader("x-rpt-htmlfilter")`)
The value if this configuration can easily be parsed with the following Regex Pattern
(parameter|header)[\s]([^\s])
Where the first captured group will be either `parameter` or `header` and the second captured group will be the key to look for.
Involvement
The filter must get involved in a request if and only if the following conditions are true
1. The configuation `enable.htmlfilter{Boolean}` is set to `true`
2. The request content type has the mime type "text/html" or "text/html+xml"
3. The either the `htmlfilter.input` request parameter or request header was provided in the request
Errors
If invalid parameters are passed to the htmlfilter (e.g. the "glue" property is passed as a number), the htmlfilter MUST change the current response status to an HTTP 400 Bad Request and log the error details in the server log.
smacdonald2008
smacdonald2008
09-05-2018
A servelt is a service running in the OSGi service container. If you are using DS Annotations - there is no more @SlingServlet annotations, Everything uses @Component now. See - Official OSGi Declarative Services Annotations in AEM - Adobe Experience Manager | AEM/CQ | Apache S...
naveent23995593
naveent23995593
09-05-2018
this is our seervlet i want to make a service this servlet...???
package com.aem.community.core.servlets;
import java.io.IOException;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.servlet.ServletException;
import org.apache.felix.scr.annotations.Service;
import org.apache.felix.scr.annotations.sling.SlingServlet;
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.SlingAllMethodsServlet;
import org.apache.sling.commons.json.JSONArray;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.JSONObject;
import org.apache.sling.commons.json.jcr.JsonJcrNode;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Component(enabled = true, immediate = true)
@SlingServlet(resourceTypes="sling/servlet/default",selectors="childlist",methods="GET",ex tensions="json",metatype=true)
public class ChildList extends SlingAllMethodsServlet {
protected final Logger loger = LoggerFactory.getLogger(ChildList.class);
private static final long serialVersionUID = 9176255033916949528L;
private JSONArray array;
@Override
public void doGet(final SlingHttpServletRequest request, final SlingHttpServletResponse response)
throws ServletException, IOException {
try{
ResourceResolver resolver = request.getResourceResolver();
Resource resource = resolver.getResource(request.getRequestPathInfo().getResourcePath());
Node node = null;
if (resource != null) {
node = resource.adaptTo(Node.class);
}
if (node == null){
throw new RepositoryException();
}
NodeIterator it = node.getNodes();
array = new JSONArray();
while (it.hasNext()) {
Node child = it.nextNode();
if (loger.isDebugEnabled()){
loger.debug("resource......."+child.getPath());
}
JSONObject obj = new JsonJcrNode(child);
array.put(obj);
response.setContentType("application/json");
response.getOutputStream().print(array.toString());
}
}
catch(RepositoryException e) {
throw new ServletException("404 HTTP ERROR Page Not Found", e);
}
catch(JSONException e)
{
loger.error("Could not formulate JSON response");
throw new ServletException("Error", e);
}
}
}
naveent23995593
naveent23995593
09-05-2018
how to create our servlet as a osgi service
Jörg_Hoh
Employee
Jörg_Hoh
Employee
08-05-2018
Hi,
unittests ran as part of the build process, and you don't need to deploy the package to your local instance. If you want to do integration tests, then you need to deploy the code first to an AEM instance and run a testsuite against it.
In that case writing unittests for AEM is not any different than writing unittests for any other framework or technology. Just the frameworks helping you are different. But the general approach is 100% identical.
Jörg
naveent23995593
naveent23995593
08-05-2018
again same issue
naveent23995593
naveent23995593
08-05-2018
yeah already added dependency uberjar 6.2
smacdonald2008
smacdonald2008
08-05-2018
You will have to modify the dependencies to work with AEM 6.2. Try rebuilding this code with AEM Maven 10 archetype and UBER 6.2 JAR file.
naveent23995593
naveent23995593
08-05-2018
am using 6.2 version
smacdonald2008
smacdonald2008
08-05-2018
Did you fork this repo and download it -- cqdump/unittests at master · joerghoh/cqdump · GitHub
It builds as i showed the build results. I also deployed it successfully.
WHat version of AEM are you using?
naveent23995593
naveent23995593
08-05-2018
org.apache.sling.api.servlets,version=[2.2,3) -- Cannot be resolved
org.apache.sling.api.resource,version=[2.10,3) -- Cannot be resolved
smacdonald2008
smacdonald2008
08-05-2018
Did you take Joergs example and execute it - I built his example and it works
Let us know if you executed this and inspected in detail the Java app logic here.
naveent23995593
naveent23995593
08-05-2018
that's why am asking you guys execute our code in ur local write unit test for it...plz guys dnt mind..,
am requesting...
naveent23995593
naveent23995593
08-05-2018
in that while am executing junit test class am getting so many errors occured..
smacdonald2008
smacdonald2008
08-05-2018
Joerg has pointed you to a lot of code that uses MOCK APIs.
naveent23995593
naveent23995593
08-05-2018
this is my test class ...i written 2 test cases with help of Httpclientreq class
public class ChildListTest
{
private static String path;
public String getPath() {
return path;
}
@SuppressWarnings({ "static-access" })
@Test
public void urlTest() throws HttpException, IOException
{
path="/apps.childlist.json";
HttpClientReq main=new HttpClientReq();
main.authenticateMethod();
assertEquals(200,main.getStatus());
}
@SuppressWarnings("static-access")
@Test
public void urlTest2() throws HttpException, IOException
{
path="/content.childlist.json";
HttpClientReq main=new HttpClientReq();
main.authenticateMethod();
assertEquals(200,main.getStatus());
}
}
naveent23995593
naveent23995593
08-05-2018
that is i know where am write test class..,in test class i written using httpclient get status code , with that status code i done test case,,but i want using mock objects check those test cases
public class HttpClientReq
{
private static final String PROTOCOL = "http";
private static final int PORT = 4502;
private static final String HOST = "localhost";
private static final String COOKIE_NAME = "login-token";
private static GetMethod get;
private static String username = "admin";
private static String password = "admin";
private static int status;
public static GetMethod getGet() {
return get;
}
public static int getStatus() {
return status;
}
public static void setStatus(int status) {
HttpClientReq.status = status;
}
public static void setGet(GetMethod get) {
HttpClientReq.get = get;
}
public static void authenticateMethod() throws HttpException, IOException
{
ChildListTest list=new ChildListTest();
HttpClient client = new HttpClient();
String token = getStatus(username, password, client);
if (token == null) {
System.err.println("No login cookie set.");
return;
}
// System.out.println("token = " + token);
get = new GetMethod(String.format("%s://%s:%s%s", PROTOCOL, HOST, PORT,list.getPath()));
get.addRequestHeader("Cookie", String.format("%s=%s", COOKIE_NAME, token));
int status = client.executeMethod(get);
if (status == 200) {
//System.out.println("response="+get.getResponseBodyAsString());
} else {
System.err
.println("Unexcepted response code " + status + "; msg: " + get.getResponseBodyAsString());
}
}
private static String getStatus(String username, String password, HttpClient client) throws IOException,
HttpException {
String token = null;
PostMethod authRequest = new PostMethod(String.format("%s://%s:%s/j_security_check", PROTOCOL, HOST, PORT));
authRequest.setParameter("j_username", username);
authRequest.setParameter("j_password", password);
authRequest.setParameter("j_validate", "true");
status = client.executeMethod(authRequest);
if (status == 200) {
Header[] headers = authRequest.getResponseHeaders("Set-Cookie");
for (Header header : headers) {
String value = header.getValue();
// System.out.println("valueee="+value);
if (value.startsWith(COOKIE_NAME + "=")) {
int endIdx = value.indexOf(';');
if (endIdx > 0) {
token = value.substring(COOKIE_NAME.length() + 1, endIdx);
}
}
}
}
else {
System.err
.println("Unexcepted response code " + status + "; msg: " + authRequest.getResponseBodyAsString());
}
return token;
}
}
smacdonald2008
smacdonald2008
08-05-2018
WHen you create a Maven 12 Archetype:
Creating an Adobe Experience Manager 6.3 Project using Adobe Maven Archetype 12
Notice the Java classes under Test package. You can write a test from the default test classes to call your servlet using HTTP APIS and do an assert on the return values. I would start with that.
If you do not know how to call a servlet using HTTP APIS - look here - Adobe Experience Manager Help | Invoking Adobe Experience Manager Sling Servlets using Apache HTTP A...
naveent23995593
naveent23995593
08-05-2018
and am referred documentation also i didn't get anything..
naveent23995593
naveent23995593
08-05-2018
actually this is first time for unittesting.. i dnt know, how to invoke servlet in test class and from test class how to send req and get response..,
smacdonald2008
smacdonald2008
08-05-2018
Have you invoked the servlet in a test and run an assert?
naveent23995593
naveent23995593
08-05-2018
please guyss help for me.....am trying a lot
naveent23995593
naveent23995593
08-05-2018
hi Jörg Hoh , still didnt get any solution.., http://localhost:4502/content.childlist.json am passing this url ,that time our childlist servlet is invoked, and am getting response jsonarray properties of under /content childnodes ..now i need unittesting for servlet.,
so please write atleast one testcase code and send me..plzzzz... this my jsonarray response.
this is my servlet code
import java.io.IOException;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.servlet.ServletException;
import org.apache.felix.scr.annotations.Service;
import org.apache.felix.scr.annotations.sling.SlingServlet;
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.SlingAllMethodsServlet;
import org.apache.sling.commons.json.JSONArray;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.JSONObject;
import org.apache.sling.commons.json.jcr.JsonJcrNode;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Component(enabled = true, immediate = true)
@Service(ChildList.class)
@SlingServlet(resourceTypes="sling/servlet/default",selectors="childlist",methods="GET",ex tensions="json",metatype=true)
public class ChildList extends SlingAllMethodsServlet {
protected final Logger loger = LoggerFactory.getLogger(ChildList.class);
private static final long serialVersionUID = 9176255033916949528L;
private JSONArray array;
@Override
public void doGet(final SlingHttpServletRequest request, final SlingHttpServletResponse response)
throws ServletException, IOException {
try{
ResourceResolver resolver = request.getResourceResolver();
Resource resource = resolver.getResource(request.getRequestPathInfo().getResourcePath());
Node node = null;
if (resource != null) {
node = resource.adaptTo(Node.class);
}
if (node == null){
throw new RepositoryException();
}
NodeIterator it = node.getNodes();
array = new JSONArray();
while (it.hasNext()) {
Node child = it.nextNode();
if (loger.isDebugEnabled()){
loger.debug("resource......."+child.getPath());
}
JSONObject obj = new JsonJcrNode(child);
array.put(obj);
response.setContentType("application/json");
response.getOutputStream().print(array.toString());
}
}
catch(RepositoryException e) {
throw new ServletException("404 HTTP ERROR Page Not Found", e);
}
catch(JSONException e)
{
loger.error("Could not formulate JSON response");
throw new ServletException("Error", e);
}
}
}
Jörg_Hoh
Employee
Jörg_Hoh
Employee
04-05-2018
Sorry, I don't understand your question. What do you want to achieve?
Jörg
naveent23995593
naveent23995593
04-05-2018
how to servlet can be disabled by the bundle configuration: enable.childlist.filter {Boolean}
??????.
naveent23995593
naveent23995593
03-05-2018
ok thanq
Jörg_Hoh
Employee
Jörg_Hoh
Employee
03-05-2018
I am sorry, it's really hard to help here without having access to the complete code.
I just retested my code at the mentioned github URL and it compiles ; maybe you can start there and try if it compiles on your system as well. As your initial request I provided you a sample how a unittest can look like.
And then as a second step you can try to transfer the settings to your environment/code.
Jörg