From 588fbcf0e757f38396c071f6db496e9c8fe1d39a Mon Sep 17 00:00:00 2001 From: j2blake Date: Mon, 30 Apr 2012 19:47:37 +0000 Subject: [PATCH] Add some unit tests to JsonServlet --- .../controller/json/JsonServletTest.java | 246 ++++++++++++++++ .../vitro/webapp/dao/VClassDaoStub.java | 264 ++++++++++++++++++ .../servlet/http/HttpServletResponseStub.java | 35 ++- .../solr/client/solrj/SolrServerStub.java | 46 +++ 4 files changed, 579 insertions(+), 12 deletions(-) create mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/controller/json/JsonServletTest.java create mode 100644 webapp/test/stubs/edu/cornell/mannlib/vitro/webapp/dao/VClassDaoStub.java create mode 100644 webapp/test/stubs/org/apache/solr/client/solrj/SolrServerStub.java diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/json/JsonServletTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/json/JsonServletTest.java new file mode 100644 index 000000000..827e3c7ae --- /dev/null +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/json/JsonServletTest.java @@ -0,0 +1,246 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.controller.json; + +import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; +import static javax.servlet.http.HttpServletResponse.SC_OK; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import java.io.IOException; + +import javax.servlet.ServletException; + +import org.apache.log4j.Level; +import org.json.JSONException; +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; + +import stubs.edu.cornell.mannlib.vitro.webapp.dao.VClassDaoStub; +import stubs.edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactoryStub; +import stubs.javax.servlet.ServletConfigStub; +import stubs.javax.servlet.ServletContextStub; +import stubs.javax.servlet.http.HttpServletRequestStub; +import stubs.javax.servlet.http.HttpServletResponseStub; +import stubs.javax.servlet.http.HttpSessionStub; +import stubs.org.apache.solr.client.solrj.SolrServerStub; +import edu.cornell.mannlib.vitro.testing.AbstractTestClass; +import edu.cornell.mannlib.vitro.webapp.beans.VClass; +import edu.cornell.mannlib.vitro.webapp.search.solr.SolrSetup; + +/** + * TODO + */ +public class JsonServletTest extends AbstractTestClass { + private static final String GET_SOLR_INDIVIDUALS_BY_VCLASS = "getSolrIndividualsByVClass"; + + private static final String GET_VCLASSES_FOR_VCLASS_GROUP = "getVClassesForVClassGroup"; + + private static final String VCLASS_ID = "vclassId"; + + /** + * Test plan + * + *
+	 * 
+	 * GetEntitiesByVClass, GetEntitiesByVClassContinuation
+	 * 	from ents_edit.js
+	 * 		ents_edit_head.jsp
+	 *  (there is an ents_edit.jsp, invoked from EntityEditController, which does not seem to invoke ents_edit.js)
+	 * 
+	 * GetSolrIndividualsByVClass
+	 * 	Mock out SolrServer (from SolrSetup) and IndividualDao
+	 *  invoked by BrowseDataGetter.java
+	 *  	home page
+	 *  invoked by ClassGroupPageData.java
+	 *  	>>>> Bring up "People" tab.
+	 *  invoked by BrowseWidget.java
+	 * 
+	 * GetSolrIndividualsByVClasses
+	 * 	Mock out SolrServer (from SolrSetup) and IndividualDao
+	 *  invoked by IndividualsForClassesDataGetter.java
+	 *  	ProcessIndividualsForClasses
+	 *  		extended in vivo by ProcessInternalClasses
+	 *  		SelectDataGetterUtils.java
+	 *  	SelectDataGetterUtils
+	 *  		MenuManagementEdit.java
+	 *  		MenuManagementController.java
+	 *  	extended in vivo by InternalClassesDataGetter, also invoked by SelectDataGetterUtils
+	 * 
+	 * GetDataForPage
+	 * 	Mock out PageDao
+	 * 
+ */ + + private JsonServlet servlet; + private ServletConfigStub config; + private ServletContextStub ctx; + private HttpSessionStub session; + private HttpServletRequestStub req; + private HttpServletResponseStub resp; + + private WebappDaoFactoryStub wadf; + private VClassDaoStub vcDao; + + private SolrServerStub solr; + + @Before + public void setup() throws ServletException { + ctx = new ServletContextStub(); + + session = new HttpSessionStub(); + session.setServletContext(ctx); + + config = new ServletConfigStub(); + config.setServletContext(ctx); + + servlet = new JsonServlet(); + servlet.init(config); + + req = new HttpServletRequestStub(); + req.setMethod("GET"); + req.setSession(session); + + resp = new HttpServletResponseStub(); + + wadf = new WebappDaoFactoryStub(); + req.setAttribute("webappDaoFactory", wadf); + ctx.setAttribute("webappDaoFactory", wadf); + + vcDao = new VClassDaoStub(); + wadf.setVClassDao(vcDao); + + solr = new SolrServerStub(); + ctx.setAttribute(SolrSetup.SOLR_SERVER, solr); + } + + @Test + public void noRecognizedRequestParameters() throws ServletException, + IOException { + servlet.service(req, resp); + assertEquals("empty response", "", resp.getOutput()); + assertEquals("status=ok", SC_OK, resp.getStatus()); + } + + @Test + public void vclassesNoClassgroup() throws ServletException, IOException { + req.addParameter(GET_VCLASSES_FOR_VCLASS_GROUP, "true"); + servlet.service(req, resp); + assertEquals("empty response", "", resp.getOutput()); + assertEquals("status=failure", SC_INTERNAL_SERVER_ERROR, + resp.getStatus()); + } + + /** + * TODO Modify VClassGroupCache so it can be stubbed out. JsonServlet asks + * VClassGroupCache for the current instance, and VClassGroupCache is a + * concrete class instead of an interface, so we can't replace the instance + * with one we like better. Furthermore, VClassGroupCache has a private + * constructor, so we can't change its behavior at all. + * + * Also test: success but no VClasses found, success with one VClass, + * success with multiple VClasses. In each case, confirm proper status, + * character encoding, and content type on the response. + */ + @Ignore + @Test + public void vclassesClassgroupNotRecognized() throws ServletException, + IOException { + req.addParameter(GET_VCLASSES_FOR_VCLASS_GROUP, "true"); + req.addParameter("classgroupUri", "http://bogusUri"); + servlet.service(req, resp); + assertEquals("empty response", "", resp.getOutput()); + assertEquals("status=failure", SC_INTERNAL_SERVER_ERROR, + resp.getStatus()); + } + + @Test + public void individualsByClassNoVClass() throws ServletException, + IOException { + setLoggerLevel(JsonServlet.class, Level.FATAL); + req.addParameter(GET_SOLR_INDIVIDUALS_BY_VCLASS, "true"); + servlet.service(req, resp); + assertFailureWithErrorMessage("java.lang.Exception: " + + "parameter vclassId URI parameter expected "); + } + + @Test + public void individualsByClassUnrecognizedVClass() throws ServletException, + IOException { + setLoggerLevel(JsonServlet.class, Level.FATAL); + String vclassId = "http://bogusVclass"; + req.addParameter(GET_SOLR_INDIVIDUALS_BY_VCLASS, "true"); + req.addParameter(VCLASS_ID, vclassId); + + servlet.service(req, resp); + assertFailureWithErrorMessage("java.lang.Exception: " + "Class " + + vclassId + " not found"); + } + + /** + * TODO test successful responses. This will require figuring out how to + * stub SolrServer. It's an abstract class, so we just need to figure out + * what sort of NamedList is required as a response to a request. + */ + @Test + public void individualsByClassNoIndividuals() throws ServletException, + IOException { + setLoggerLevel(JsonServlet.class, Level.FATAL); + String vclassId = "http://myVclass"; + vcDao.setVClass(vclassId, new VClass(vclassId)); + req.addParameter(GET_SOLR_INDIVIDUALS_BY_VCLASS, "true"); + req.addParameter(VCLASS_ID, vclassId); + + servlet.service(req, resp); + assertSuccessWithIndividuals(vclassId, 0); + } + + // ---------------------------------------------------------------------- + // Helper methods + // ---------------------------------------------------------------------- + + /** + * The response should be a JSONObject that contained this error-message, + * and the status should be set to INTERNAL_SERVER_ERROR. + */ + private void assertFailureWithErrorMessage(String expected) { + try { + JSONObject result = new JSONObject(resp.getOutput()); + assertEquals("errorMessage", expected, + getFieldValue(result, "errorMessage")); + assertEquals("status", SC_INTERNAL_SERVER_ERROR, resp.getStatus()); + } catch (JSONException e) { + fail(e.toString()); + } + } + + private void assertSuccessWithIndividuals(String vclassId, int count) { + try { + JSONObject actual = new JSONObject(resp.getOutput()); + assertEquals("errorMessage", "", + getFieldValue(actual, "errorMessage")); + assertEquals("count", count, getFieldValue(actual, "totalCount")); + + JSONObject vclassObj = (JSONObject) getFieldValue(actual, "vclass"); + assertEquals("vclass name", vclassId.split("://")[1], getFieldValue(vclassObj, "name")); + assertEquals("vclass uri", vclassId, getFieldValue(vclassObj, "URI")); + + assertEquals("status", SC_OK, resp.getStatus()); + } catch (JSONException e) { + fail(e.toString()); + } + } + + private Object getFieldValue(JSONObject json, String fieldName) { + try { + assertEquals("find " + fieldName, true, json.has(fieldName)); + return json.get(fieldName); + } catch (JSONException e) { + fail(e.toString()); + return -1; + } + } + +} diff --git a/webapp/test/stubs/edu/cornell/mannlib/vitro/webapp/dao/VClassDaoStub.java b/webapp/test/stubs/edu/cornell/mannlib/vitro/webapp/dao/VClassDaoStub.java new file mode 100644 index 000000000..3c912c72e --- /dev/null +++ b/webapp/test/stubs/edu/cornell/mannlib/vitro/webapp/dao/VClassDaoStub.java @@ -0,0 +1,264 @@ +package stubs.edu.cornell.mannlib.vitro.webapp.dao; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import edu.cornell.mannlib.vitro.webapp.beans.Classes2Classes; +import edu.cornell.mannlib.vitro.webapp.beans.VClass; +import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup; +import edu.cornell.mannlib.vitro.webapp.dao.InsertException; +import edu.cornell.mannlib.vitro.webapp.dao.VClassDao; + +public class VClassDaoStub implements VClassDao { +// ---------------------------------------------------------------------- +// Stub infrastructure +// ---------------------------------------------------------------------- + + private final Map vclassesByUri = new HashMap(); + + public void setVClass(String uri, VClass vclass) { + vclassesByUri.put(uri, vclass); + } + +// ---------------------------------------------------------------------- +// Stub methods +// ---------------------------------------------------------------------- + + @Override + public VClass getVClassByURI(String URI) { + return vclassesByUri.get(URI); + } + +// ---------------------------------------------------------------------- +// Un-implemented methods +// ---------------------------------------------------------------------- + + + @Override + public List getRootClasses() { + throw new RuntimeException( + "VClassDaoStub.getRootClasses() not implemented."); + } + + @Override + public List getOntologyRootClasses(String ontologyURI) { + throw new RuntimeException( + "VClassDaoStub.getOntologyRootClasses() not implemented."); + } + + @Override + public List getAllVclasses() { + throw new RuntimeException( + "VClassDaoStub.getAllVclasses() not implemented."); + } + + @Override + public List getDisjointWithClassURIs(String vclassURI) { + throw new RuntimeException( + "VClassDaoStub.getDisjointWithClassURIs() not implemented."); + } + + @Override + public void addSuperclass(VClass subclass, VClass superclass) { + throw new RuntimeException( + "VClassDaoStub.addSuperclass() not implemented."); + } + + @Override + public void addSuperclass(String classURI, String superclassURI) { + throw new RuntimeException( + "VClassDaoStub.addSuperclass() not implemented."); + } + + @Override + public void removeSuperclass(VClass vclass, VClass superclass) { + throw new RuntimeException( + "VClassDaoStub.removeSuperclass() not implemented."); + } + + @Override + public void removeSuperclass(String classURI, String superclassURI) { + throw new RuntimeException( + "VClassDaoStub.removeSuperclass() not implemented."); + } + + @Override + public void addSubclass(VClass vclass, VClass subclass) { + throw new RuntimeException( + "VClassDaoStub.addSubclass() not implemented."); + } + + @Override + public void addSubclass(String classURI, String subclassURI) { + throw new RuntimeException( + "VClassDaoStub.addSubclass() not implemented."); + } + + @Override + public void removeSubclass(VClass vclass, VClass subclass) { + throw new RuntimeException( + "VClassDaoStub.removeSubclass() not implemented."); + } + + @Override + public void removeSubclass(String classURI, String subclassURI) { + throw new RuntimeException( + "VClassDaoStub.removeSubclass() not implemented."); + } + + @Override + public void addDisjointWithClass(String classURI, String disjointCLassURI) { + throw new RuntimeException( + "VClassDaoStub.addDisjointWithClass() not implemented."); + } + + @Override + public void removeDisjointWithClass(String classURI, String disjointClassURI) { + throw new RuntimeException( + "VClassDaoStub.removeDisjointWithClass() not implemented."); + } + + @Override + public List getEquivalentClassURIs(String classURI) { + throw new RuntimeException( + "VClassDaoStub.getEquivalentClassURIs() not implemented."); + } + + @Override + public void addEquivalentClass(String classURI, String equivalentClassURI) { + throw new RuntimeException( + "VClassDaoStub.addEquivalentClass() not implemented."); + } + + @Override + public void removeEquivalentClass(String classURI, String equivalentClassURI) { + throw new RuntimeException( + "VClassDaoStub.removeEquivalentClass() not implemented."); + } + + @Override + public List getSubClassURIs(String classURI) { + throw new RuntimeException( + "VClassDaoStub.getSubClassURIs() not implemented."); + } + + @Override + public List getAllSubClassURIs(String classURI) { + throw new RuntimeException( + "VClassDaoStub.getAllSubClassURIs() not implemented."); + } + + @Override + public List getSuperClassURIs(String classURI, boolean direct) { + throw new RuntimeException( + "VClassDaoStub.getSuperClassURIs() not implemented."); + } + + @Override + public List getAllSuperClassURIs(String classURI) { + throw new RuntimeException( + "VClassDaoStub.getAllSuperClassURIs() not implemented."); + } + + @Override + public void insertNewVClass(VClass cls) throws InsertException { + throw new RuntimeException( + "VClassDaoStub.insertNewVClass() not implemented."); + } + + @Override + public void updateVClass(VClass cls) { + throw new RuntimeException( + "VClassDaoStub.updateVClass() not implemented."); + } + + @Override + public void deleteVClass(String URI) { + throw new RuntimeException( + "VClassDaoStub.deleteVClass() not implemented."); + } + + @Override + public void deleteVClass(VClass cls) { + throw new RuntimeException( + "VClassDaoStub.deleteVClass() not implemented."); + } + + @Override + public List getVClassesForProperty(String propertyURI, + boolean domainSide) { + throw new RuntimeException( + "VClassDaoStub.getVClassesForProperty() not implemented."); + } + + @Override + public List getVClassesForProperty(String vclassURI, + String propertyURI) { + throw new RuntimeException( + "VClassDaoStub.getVClassesForProperty() not implemented."); + } + + @Override + public void addVClassesToGroup(VClassGroup group) { + throw new RuntimeException( + "VClassDaoStub.addVClassesToGroup() not implemented."); + } + + @Override + public void insertNewClasses2Classes(Classes2Classes c2c) { + throw new RuntimeException( + "VClassDaoStub.insertNewClasses2Classes() not implemented."); + } + + @Override + public void deleteClasses2Classes(Classes2Classes c2c) { + throw new RuntimeException( + "VClassDaoStub.deleteClasses2Classes() not implemented."); + } + + @Override + public void addVClassesToGroup(VClassGroup group, + boolean includeUninstantiatedClasses) { + throw new RuntimeException( + "VClassDaoStub.addVClassesToGroup() not implemented."); + } + + @Override + public void addVClassesToGroup(VClassGroup group, + boolean includeUninstantiatedClasses, boolean getIndividualCount) { + throw new RuntimeException( + "VClassDaoStub.addVClassesToGroup() not implemented."); + } + + @Override + public void addVClassesToGroups(List groups) { + throw new RuntimeException( + "VClassDaoStub.addVClassesToGroups() not implemented."); + } + + @Override + public boolean isSubClassOf(VClass vc1, VClass vc2) { + throw new RuntimeException( + "VClassDaoStub.isSubClassOf() not implemented."); + } + + @Override + public boolean isSubClassOf(String vclassURI1, String vclassURI2) { + throw new RuntimeException( + "VClassDaoStub.isSubClassOf() not implemented."); + } + + @Override + public VClass getTopConcept() { + throw new RuntimeException( + "VClassDaoStub.getTopConcept() not implemented."); + } + + @Override + public VClass getBottomConcept() { + throw new RuntimeException( + "VClassDaoStub.getBottomConcept() not implemented."); + } + +} diff --git a/webapp/test/stubs/javax/servlet/http/HttpServletResponseStub.java b/webapp/test/stubs/javax/servlet/http/HttpServletResponseStub.java index df479c890..7a35e8d16 100644 --- a/webapp/test/stubs/javax/servlet/http/HttpServletResponseStub.java +++ b/webapp/test/stubs/javax/servlet/http/HttpServletResponseStub.java @@ -10,6 +10,8 @@ import java.io.StringWriter; import java.util.HashMap; import java.util.Locale; import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.servlet.ServletOutputStream; import javax.servlet.http.Cookie; @@ -29,6 +31,7 @@ public class HttpServletResponseStub implements HttpServletResponse { private String errorMessage; private Map headers = new HashMap(); private String contentType; + private String charset = ""; private ByteArrayOutputStream outputStream; private StringWriter outputWriter; @@ -129,9 +132,19 @@ public class HttpServletResponseStub implements HttpServletResponse { return headers.containsKey(name); } + /** + * Calling setContentType("this/type;charset=UTF-8") is the same as calling + * setContentType("this/type;charset=UTF-8"); setCharacterEncoding("UTF-8") + */ @Override public void setContentType(String contentType) { this.contentType = contentType; + + Pattern p = Pattern.compile(";\\scharset=([^;]+)"); + Matcher m = p.matcher(contentType); + if (m.find()) { + this.charset = m.group(1); + } } @Override @@ -139,6 +152,16 @@ public class HttpServletResponseStub implements HttpServletResponse { return contentType; } + @Override + public void setCharacterEncoding(String charset) { + this.charset = charset; + } + + @Override + public String getCharacterEncoding() { + return charset; + } + // ---------------------------------------------------------------------- // Un-implemented methods // ---------------------------------------------------------------------- @@ -155,12 +178,6 @@ public class HttpServletResponseStub implements HttpServletResponse { "HttpServletResponseStub.getBufferSize() not implemented."); } - @Override - public String getCharacterEncoding() { - throw new RuntimeException( - "HttpServletResponseStub.getCharacterEncoding() not implemented."); - } - @Override public Locale getLocale() { throw new RuntimeException( @@ -191,12 +208,6 @@ public class HttpServletResponseStub implements HttpServletResponse { "HttpServletResponseStub.setBufferSize() not implemented."); } - @Override - public void setCharacterEncoding(String arg0) { - throw new RuntimeException( - "HttpServletResponseStub.setCharacterEncoding() not implemented."); - } - @Override public void setContentLength(int arg0) { throw new RuntimeException( diff --git a/webapp/test/stubs/org/apache/solr/client/solrj/SolrServerStub.java b/webapp/test/stubs/org/apache/solr/client/solrj/SolrServerStub.java new file mode 100644 index 000000000..4fd1df48b --- /dev/null +++ b/webapp/test/stubs/org/apache/solr/client/solrj/SolrServerStub.java @@ -0,0 +1,46 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package stubs.org.apache.solr.client.solrj; + +import java.io.IOException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.solr.client.solrj.SolrRequest; +import org.apache.solr.client.solrj.SolrServer; +import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.common.util.NamedList; + +/** + * TODO + */ +public class SolrServerStub extends SolrServer { + private static final Log log = LogFactory.getLog(SolrServerStub.class); + + // ---------------------------------------------------------------------- + // Stub infrastructure + // ---------------------------------------------------------------------- + + // ---------------------------------------------------------------------- + // Stub methods + // ---------------------------------------------------------------------- + + /* + * (non-Javadoc) + * + * @see + * org.apache.solr.client.solrj.SolrServer#request(org.apache.solr.client + * .solrj.SolrRequest) + */ + @Override + public NamedList request(SolrRequest request) + throws SolrServerException, IOException { + // TODO not really an implementation. + return new NamedList(); + } + + // ---------------------------------------------------------------------- + // Un-implemented methods + // ---------------------------------------------------------------------- + +}