I am attempting to use the Struts2 JUnit Plugin (v2.2.3 w/ Struts2 v2.2.3) and have run into several issues.
I attempted to use the Struts2 JUnit Plugin Tutorial as a guide. The first change I needed to make (not in the guide) is to annotate my test class with:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath*:applicationContext-test.xml"})
because I was getting the error when trying to run my unit test:
SEVERE: [56:51.239] ********** FATAL ERROR STARTING UP STRUTS-SPRING INTEGRATION **********
Looks like the Spring listener was not configured for your web app!
Nothing will work until WebApplicationContextUtils returns a valid ApplicationContext.
You might need to add the following to web.xml:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
SEVERE: [56:51.254] Dispatcher initialization failed
This is different than the tutorial- does anyone know why I needed to do this?
I also had to add the following Spring Jars (I have the necessary Struts2 jars included in my classpath):
- spring-beans-2.5.6.jar
- spring-context-2.5.6.jar
- spring-core-2.5.6.jar
- spring-test-2.5.6.jar
- spring-web-2.5.6.jar
I do not use Spring w/in my struts app, but I assume these jars are needed to use the mock request
object and such in the StrutsTestCase
.
My Test class:
package com.actions;
import java.io.UnsupportedEncodingException;
import java.util.List;
import javax.servlet.ServletException;
import org.apache.log4j.Logger;
import org.apache.struts2.StrutsTestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.beans.LabelValueBean;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath*:applicationContext-test.xml"})
public class DocumentCategoryTest extends StrutsTestCase {
private static Logger log = Logger.getLogger(DocumentCategoryTest .class);
/**
* Testing RetrieveDocumentTypesForDocumentCategory
* Expecting the List<LabelValueBean> is not null
* @throws ServletException
* @throws UnsupportedEncodingException
*/
@Test
public void testRetrieveDocumentTypesForDocumentCategory() throws UnsupportedEncodingException, ServletException {
final String docCategory = "Employment";
//set parameters
request.setParameter("documentCategoryDescription", docCategory);
//execute the action
executeAction("/recipient/RetrieveDocumentTypesForDocumentCategory.action");
//retrieve the document types
@SuppressWarnings("unchecked")
List<LabelValueBean> testDocTypeList = (List<LabelValueBean>) findValueAfterExecute("documentTypes");
//make sure the document type list is not null and has at least one document type
assertNotNull(testDocTypeList);
assertTrue("At least one document type should exist for category 'Employment'", testDocTypeList.size() > 0);
//print types
log.debug("Document types for category '" + docCategory + "'");
log.debug(testDocTypeList);
}
}
When I execute the action, I get a NullPointerException
on the request.setParameter
piece of code:
java.lang.NullPointerException
at com.actions.DocumentCategoryTest.testRetrieveDocumentTypesForDocumentCategory(DocumentCategoryTest.java:38)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.test.context.junit4.SpringTestMethod.invoke(SpringTestMethod.java:160)
at org.springframework.test.context.junit4.SpringMethodRoadie.runTestMethod(SpringMethodRoadie.java:233)
at org.springframework.test.context.junit4.SpringMethodRoadie$RunBeforesThenTestThenAfters.run(SpringMethodRoadie.java:333)
at org.springframework.test.context.junit4.SpringMethodRoadie.runWithRepetitions(SpringMethodRoadie.java:217)
at org.springframework.test.context.junit4.SpringMethodRoadie.runTest(SpringMethodRoadie.java:197)
at org.springframework.test.context.junit4.SpringMethodRoadie.run(SpringMethodRoadie.java:143)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.invokeTestMethod(SpringJUnit4ClassRunner.java:160)
at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:97)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
This is because, for some reason, request
is null in StrutsTestCase
. Why is this? I'm doing exactly as the tutorial dictates!
My action class extends another class (BaseAction
) that extends ActionSupport
and implements SessionAware
.
package com.actions;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import com.actions.BaseAction;
/**
* Retrieves the document types for the passed in document category
*/
public class DocumentIndexingData extends BaseAction {
private static final long serialVersionUID = 1L;
private static Logger log = Logger.getLogger(DocumentIndexingData.class);
/*=========================================================================
* FIELDS
*=========================================================================*/
/**
* The description to use to look up the document types for that category
*/
private String documentCategoryDescription;
/**
* List of document types for a category
*/
private List<LabelValueBean> documentTypes;
/*=========================================================================
* PUBLIC METHODS
*=========================================================================*/
/**
* Retrieves & sets list of document types for document category with passed in ID
*
* @return If there is an error, document type will be set to ERROR; SUCCESS is always returned by this method
*/
public String retrieveDocumentTypesForDocumentCategory() {
List<LabelValueBean> docTypes = new ArrayList<LabelValueBean>();
//retrieve document types for passed in category ID
log.debug("looking up document types for category: " + getDocumentCategoryDescription());
////////////////
//retrieve the document types for the document category here...
////////////////
this.setDocumentTypes(docTypes);
log.debug("document types found: " + getDocumentTypes());
return SUCCESS;
}
/*=========================================================================
* GETTERS/SETTERS
*=========================================================================*/
/**
* Retrieves the list of document types
*
* @return list of document types
*/
public List<LabelValueBean> getDocumentTypes() {
return documentTypes;
}
/**
* Sets the list of document types
*
* @param documentTypes
*/
public void setDocumentTypes(List<LabelValueBean> documentTypes) {
this.documentTypes = documentTypes;
}
/**
* Retrieves the document category to retrieve document types for
*
* @return the document category
*/
public String getDocumentCategoryDescription() {
return documentCategoryDescription;
}
/**
* Sets the document category to retrieve document types for
*
* @param documentCategoryDescription the document category to retrieve document types for
*/
public void setDocumentCategoryDescription(String documentCategoryDescription) {
this.documentCategoryDescription = documentCategoryDescription;
}
}
struts.xml entry:
<!-- indexing attributes action -->
<action name="RetrieveDocumentTypesForDocumentCategory" class="com.actions.DocumentIndexingData" method="retrieveDocumentTypesForDocumentCategory">
<result type="json">
<param name="root">documentTypes</param>
</result>
</action>
I'm following the tutorial pretty closely, why is request
null? Thank you so much for any help!
UPDATE (My Solution! via @Alex): I now only have the following Struts JARs included on my classpath:
- struts2-junit-plugin-2.2.3.jar
- spring-beans-2.5.6.jar
- spring-context-2.5.6.jar
- spring-core-2.5.6.jar
- spring-test-2.5.6.jar
- spring-web-2.5.6.jar
Sample test:
public class MyTest extends StrutsTestCase { @Test public void testMyAction() throws Exception { request.setParameter("aParameter", "aValue"); //create action proxy ActionProxy proxy = getActionProxy("/test/MyAction"); assertNotNull(proxy); MyAction action = (MyAction) proxy.getAction(); assertNotNull(action); //execute the action String result = proxy.execute(); //make assertions, expecting success and no error messags assertTrue("There should be no field errors: " + action.getFieldErrors(), action.getFieldErrors().size() == 0); assertTrue("There should be no action errors: " + action.getActionErrors(), action.getActionErrors().size() == 0); assertEquals("Result did not match expected value; ", Action.SUCCESS, result); } }