I am trying to develop JUnit4 test scripts for our application that uses Spring 3.2.2 and Struts 2.3.12. I think I am close to getting this working but for some reason when executeAction is called or getActionProxy is called I am getting a null pointer error because method does not exist. Am I not passing the correct uri? or is it something more I am missing. This is a maven project so all of the I am using the following:
struts2-junit-plugin-2.3.13.jar struts 2.3.12 (core, spring plugin, dojo plugin, json plugin, sitemesh plugin) Spring 3.2.2 (core, web, context, expression, context-support, aop, aspects, test)
This is my simple test:
package com.execupharm.lms.web.action.administration.test;
import static org.junit.Assert.assertFalse;
import org.apache.struts2.StrutsSpringJUnit4TestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.execupharm.lms.web.action.administration.DashboardAction;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration( { "classpath:applicationContextWeb.xml",
"classpath:applicationContextSecurity.xml",
"classpath:applicationContextService.xml",
"classpath:applicationContextDao.xml",
"classpath:applicationContextMail.xml" })
public class DashboardActionTest extends StrutsSpringJUnit4TestCase<DashboardAction> {
@Test
public void executeTest() throws Exception {
String result = executeAction("/administration/dashboard.action");
System.out.println("result = " + result);
//DashboardAction action = getAction();
assertFalse(containsErrors());
}
/**
* Override this method to return a comma separated list of paths to a
configuration
* file.
* <p>The default implementation simply returns <code>null</code>.
*
* @return a comma separated list of config locations
*/
@Override
protected String getConfigPath() {
return "classpath:struts.xml";
}
}
All of our context*.xml files are in the src/main/resources folder:
applicationContextDao.xml
applicationContextMail.xml
applicationContextSecurity.xml
applicationContextService.xml
applicationContextWeb.xml
struts.xml
This is our struts file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<!-- Constants -->
<constant name="struts.locale" value="en"/>
<constant name="struts.devMode" value="false" />
<constant name="struts.i18n.encoding" value="UTF-8" />
<constant name="struts.action.extension" value="action" />
<constant name="struts.objectFactory" value="spring" />
<constant name="struts.objectFactory.spring.autoWire" value="name" />
<constant name="struts.objectFactory.spring.useClassCache" value="true" />
<constant name="struts.custom.i18n.resources" value="app_resources" />
<constant name="struts.multipart.maxSize" value="12000000" />
<constant name="struts.multipart.saveDir" value="/LMS_Media" />
<constant name="struts.multipart.parser" value="jakarta" />
<constant name="struts.codebehind.pathPrefix" value="/WEB-INF/jsp/" />
<constant name="struts.enable.SlashesInActionNames" value="true" />
<constant name="struts.url.http.port" value="80" />
<constant name="struts.date.format" value="MM/dd/yyyy" />
<!-- Configuration for the default package. -->
<package name="default" extends="struts-default,json-default" namespace="/">
<interceptors>
<interceptor name="permissionsInterceptor"
class="com.execupharm.lms.web.interceptor.PermissionsInterceptor" />
<interceptor name="employeeIdResolverInterceptor"
class="com.execupharm.lms.web.interceptor.EmployeeIdResolverInterceptor" />
<!--
Copied from struts-default.xml and changed validation exclude
methods
-->
<interceptor-stack name="defaultStack">
<interceptor-ref name="exception">
<param name="logEnabled">true</param>
<param name="logLevel">ERROR</param>
<param name="logCategory">com.execupharm.lms</param>
</interceptor-ref>
<interceptor-ref name="alias" />
<interceptor-ref name="servletConfig" />
<interceptor-ref name="params">
<!--
Excludes the jQuery no-cache _ parameter and our own search.
params
-->
<param name="excludeParams">
_,search\..*
</param>
</interceptor-ref>
<interceptor-ref name="prepare" />
<interceptor-ref name="i18n" />
<interceptor-ref name="chain" />
<interceptor-ref name="debugging" />
<interceptor-ref name="profiling" />
<interceptor-ref name="scopedModelDriven" />
<interceptor-ref name="modelDriven" />
<interceptor-ref name="fileUpload" />
<interceptor-ref name="checkbox" />
<interceptor-ref name="staticParams" />
<interceptor-ref name="params">
<param name="excludeParams">dojo\..*</param>
</interceptor-ref>
<interceptor-ref name="conversionError" />
<interceptor-ref name="validation">
<param name="excludeMethods">cancel,execute,delete,edit,list</param>
</interceptor-ref>
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel,browse,execute</param>
</interceptor-ref>
<interceptor-ref name="permissionsInterceptor" />
<interceptor-ref name="employeeIdResolverInterceptor" />
</interceptor-stack>
</interceptors>
<global-results>
<result name="error">/error.jsp</result>
<result name="forbidden">/forbidden.jsp</result>
</global-results>
<action name="login" class="loginAction">
<result name="success">/login.jsp</result>
</action>
<action name="logout" class="logoutAction">
<result name="success" type="redirect">/login.action</result>
</action>
</package>
<!-- End Default Package -->
<!-- Administration -->
<package name="administration" extends="default" namespace="/administration">
<action name="dashboard" class="dashboardAction">
<result name="success">/WEB-INF/jsp/administration/dashboard.jsp
</result>
</action>
<action name="addTraining" class="addTrainingAction">
<result name="success">/WEB-INF/jsp/training/addTraining.jsp
</result>
</action>
<action name="searchSOPs" class="searchSOPsAction">
<result name="success">/WEB-INF/jsp/training/searchSOPs.jsp
</result>
</action>
<action name="searchTests" class="searchTestsAction">
<result name="success">/WEB-INF/jsp/training/searchTests.jsp
</result>
</action>
<action name="viewTraining" class="viewTrainingAction">
<result name="success">/WEB-INF/jsp/training/viewTraining.jsp
</result>
</action>
<action name="viewSOP" class="viewSOPAction">
<result name="success">/WEB-INF/jsp/training/viewSOP.jsp
</result>
</action>
<action name="viewSOPSave" class="viewSOPAction" method="save">
<result name="input">/WEB-INF/jsp/training/viewSOP.jsp
</result>
<result name="success" type="redirect">dashboard.action
</result>
</action>
<action name="viewTest" class="viewTestAction">
<result name="success">/WEB-INF/jsp/training/viewTest.jsp
</result>
</action>
<action name="viewMedia" class="viewMediaAction">
<result name="success">/WEB-INF/jsp/training/viewMedia.jsp
</result>
</action>
</package>
<package name="training" extends="default" namespace="/training">
</package>
</struts>
applicationContextWeb.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<bean id="loginAction" class="com.execupharm.lms.web.action.LoginAction" scope="prototype"/>
<bean id="logoutAction" class="com.execupharm.lms.web.action.LogoutAction" scope="prototype"/>
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>
<context:annotation-config />
<bean id="dashboardAction" class="com.execupharm.lms.web.action.administration.DashboardAction" scope="prototype" />
<bean id="addTrainingAction" class="com.execupharm.lms.web.action.training.AddTrainingAction" scope="prototype" />
<bean id="searchSOPsAction" class="com.execupharm.lms.web.action.training.SearchSOPsAction" scope="prototype" />
<bean id="searchTestsAction" class="com.execupharm.lms.web.action.training.SearchTestsAction" scope="prototype" />
<bean id="viewTrainingAction" class="com.execupharm.lms.web.action.training.ViewTrainingAction" scope="prototype" />
<bean id="viewSOPAction" class="com.execupharm.lms.web.action.training.ViewSOPAction" scope="prototype" />
<bean id="viewTestAction" class="com.execupharm.lms.web.action.training.ViewTestAction" scope="prototype" />
<bean id="viewMediaAction" class="com.execupharm.lms.web.action.training.ViewMediaAction" scope="prototype" />
</beans>
This is the error we are getting that we are getting:
java.lang.NullPointerException
at org.apache.struts2.impl.StrutsActionProxy.getErrorMessage(StrutsActionProxy.java:69)
at com.opensymphony.xwork2.DefaultActionProxy.prepare(DefaultActionProxy.java:185)
at org.apache.struts2.impl.StrutsActionProxy.prepare(StrutsActionProxy.java:63)
at org.apache.struts2.impl.StrutsActionProxyFactory.createActionProxy(StrutsActionProxyFactory.java:39)
at com.opensymphony.xwork2.DefaultActionProxyFactory.createActionProxy(DefaultActionProxyFactory.java:58)
at org.apache.struts2.StrutsJUnit4TestCase.getActionProxy(StrutsJUnit4TestCase.java:149)
at com.execupharm.lms.web.action.administration.test.DashboardActionTest.executeTest(DashboardActionTest.java:24)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
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)
I have tried calling the executeAction with the following as well:
String result = executeAction("/administration/dashboard.action");
String result = executeAction("/dashboardAction");
String result = executeAction("/administration/dashboard");
Maybe I need to take a new approach to this. Just thought the plugin was going to make this easy, but it is not looking like that.
Thanks!
I wouldn't call it a unit test if you have Struts and Spring involved. That's an integration test.
Looks to me like that
containsErrors()
method in the assert isn't checking to see if errors is null.