Expand my Community achievements bar.

SOLVED

how to do servlet unit testing

Avatar

Level 3

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

}

}

}

1 Accepted Solution

Avatar

Correct answer by
Employee Advisor

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

View solution in original post

50 Replies

Avatar

Administrator

Here is a GEMS Session where they cover JUNIT Testing - From Unit Testing to Integration Test of an AEM Application

A COMMUNITY ARTICLE TO HELP YOU:- http://keysandstrokes.info/aem-apache-sling-testing/

Also, some reference post wcm.io Testing | Testing



Kautuk Sahni

Avatar

Level 3

i reffered these things,but i din't get anything, this is 1st time to doing unittesing for servlet in aem., can u write servlet unittesting testcases  how to write , how to get resources ,how to json data equals

Avatar

Level 10

Have you looked at the default test package when you generate a maven archetype 12/13 project.

You can use JUNIT code to test application logic here. For example - here a model class.  WHen you build the maven project - you can see the Tests run and the results.

TestClass.png

Avatar

Level 3

hi bro..i written like this

@RunWith(MockitoJUnitRunner.class)

public class ChildListTest {

@InjectMocks

private ChildList childlist;

@Mock

private SlingHttpServletRequest request;

@Mock

private SlingHttpServletResponse response;

@Mock

Resource resource;

Logger LOGGER;

@Mock

Node nodes;

@Mock

private ResourceResolverFactory resourceResolverFactory;

@Rule

public final AemContext context = new AemContext();

@Before

public void setup() {

//childlist=new ChildList();

MockitoAnnotations.initMocks(this);

}

@Test

public void testDoGet() throws ServletException, IOException, RepositoryException, JSONException

{

/*//childlist.doGet(context.request(),context.response());

resource = context.resourceResolver().getResource("/content");

ResourceResolver resolver = request.getResourceResolver();

resource = resolver.getResource(request.getRequestPathInfo().getResourcePath());

nodes=resource.adaptTo(Node.class);

NodeIterator it=nodes.getNodes();

}

}

Avatar

Level 3

i written testing in eclipse  maven archetype10, but how get request from servlet,, how to test servlet class and how link with test class and servlet class,and these servlet class how can i get response without running ...

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",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);

}

}

}

Avatar

Level 10

Try creating another class in the test package. Then use Java APIs to invoke the Servlet and use  assertTrue on the value the servlet returns.

Also - you do not need @Component and @Servlet when using @SlingServlet.

Avatar

Level 10

Invoke the Servlet using JAVA HTTP APIS -- something like:

@Test

    public void testinvokeServlet() throws Exception {

        // some very basic junit tests

        <PUT IN JAVA HTTP CODE TO CALL SERVLET>

        assertTrue(msg.length() > 0);

    }

ie --

//Create an HTTPClient object

        HttpClient client = new HttpClient();

        HttpMethod method = new GetMethod("http://localhost:4502/bin/mySearchServlet");

Avatar

Level 3

with that @Slingservlet ex:http://localhost:4502/content.childlist.json  whenever hit this url we can get jsonarray for node properties.,

actaul requirement ->This web service is mounted to the selector .childlist.json. Given any node path, it returns a JSONArray of the node's child node paths and properties.

so that's why i created servlet with selector.extension

Avatar

Level 10

You should still be able to invoke it using Java HTTP API and use an asset call to test return value.

Avatar

Employee Advisor

I'd look into using Sling Mocks or other mocking frameworks to simulate complex objects that are impractical to incorporate into the unit test. The goal should be to isolate and test behavior of the code within the servlet, not necessarily the servlet itself. Check out Sling Mocks: Apache Sling :: Sling Mocks . Mocks can be used to unit test code prior to deployment.

If you do want to some more real-world testing (on say a stage/QA environment) you can also look into server side integration testing as well: https://sling.apache.org/documentation/development/sling-testing-tools.htm (Maven achetype 13 has an example of server-side integration test). These will be executed after code is deployed to the AEM environment.

Avatar

Level 3

if u dnt mind.., execute my code in ur ide, and write unittest for our code,and send me

plz guys this is my 1st time usnit testing i dnt know how run how to write in aem

Avatar

Correct answer by
Employee Advisor

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

Avatar

Level 3

i did't get it..https://github.com/joerghoh/cqdump/blob/master/unittests/core/src/main/java/de/joerghoh/cqdump/core/...   why it is using ChildListOptimized.java..,

private JSONObject convertResourceToJSON (Resource resource) throws JSONException {

JSONObject obj = new JSONObject();

obj.put("jcr:path", resource.getPath());

ValueMap vm = resource.adaptTo(ValueMap.class);

vm.forEach((key,value) -> {

vm.put(key, value);

});

return obj;

}

*  in that what is key and value it's getting error

Avatar

Employee Advisor

You can safely ignore the "optimized version" for the moment; I just wanted to demonstrate that you can easily achieve the (more or less) same functionality without using the JCR API.

Jörg

Avatar

Level 3

mvn clean install

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.2:testCompile (default-testCompile) on project aandes.core: Compilation failure

[ERROR] /C:/Users/Naveen/aandes/core/src/test/java/com/aem/community/core/models/ChildListTest.java:[49,24] cannot access org.junit.rules.TestRule

[ERROR] class file for org.junit.rules.TestRule not found

[ERROR] -> [Help 1]

Avatar

Employee Advisor

Check the pom.xml as well. Make sure that you include the "junit" dependencies.