1

我正在尝试为使用 Spring 3.2.2 和 Struts 2.3.12 的应用程序开发 JUnit4 测试脚本。我想我已经接近完成这项工作,但由于某种原因,当调用 executeAction 或 getActionProxy 时,我收到一个空指针错误,因为方法不存在。我没有传递正确的uri吗?还是我更想念的东西。这是一个 Maven 项目,所以我使用以下所有内容:

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, aspect , 测试)

这是我的简单测试:

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"; 
    }
}

我们所有的 context*.xml 文件都在 src/main/resources 文件夹中:

applicationContextDao.xml
applicationContextMail.xml
applicationContextSecurity.xml
applicationContextService.xml
applicationContextWeb.xml
struts.xml

这是我们的 struts 文件:

<?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>

这是我们得到的错误:

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)

我也尝试使用以下命令调用 executeAction:

String result = executeAction("/administration/dashboard.action");
String result = executeAction("/dashboardAction");
String result = executeAction("/administration/dashboard");

也许我需要采取一种新的方法来解决这个问题。只是以为插件会让这件事变得简单,但它看起来不像那样。

谢谢!

4

2 回答 2

1

如果您涉及 Struts 和 Spring,我不会将其称为单元测试。那是一个集成测试。

在我看来,containsErrors()断言中的那个方法没有检查错误是否为空。

于 2013-05-02T19:17:08.507 回答
0

想通了这个问题。事实证明,测试中 struts.xml 文件的覆盖由于某种原因导致了错误,并且只使用了 struts-default。一旦我删除了该行(因为它已经在类路径中,因此无需覆盖它),Junit 测试就起作用了。

于 2013-05-03T19:03:21.887 回答