无法使用 Struts2-Junit-Plugin 执行任何 StrutsTestCase,操作方法为空

Unable to execute any StrutsTestCase using Struts2-Junit-Plugin, action method is null

首先很抱歉,如果我解释得不够清楚,我会尽力而为。最近从C/C#换成了Java,有点不知所措

我正在开发一个使用 Struts2+Hibernate 的项目(我没有使用 Spring);这个想法是使用 struts2-JUnit-plugin 来测试操作。

我遵循了 strut2-junit-plugin 教程但没有成功,经过大量研究并尝试了所有可能的解决方案后,我找不到好的解决方案。

"issues"(因为我不太确定这是否是一个问题...)我遇到的是,当我尝试 运行 一个 StrutsTestCase 时,在设置过程中:

super.setUp();
initServletMockObjects();
setupBeforeInitDispatcher();
dispatcher = initDispatcher(dispatcherInitParams);
setupAfterInitDispatcher(dispatcher);

当调用 dispatcher = initDispatcher(dispatcherInitParams) 时,dispatcherInitParams 为 null 并抛出以下堆栈跟踪:

ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console...
ERROR CdiObjectFactory [findBeanManager]: Could not find BeanManager instance for any given JNDI key, giving up
ERROR CdiObjectFactory Struts2 CDI integration could not be initialized.
ERROR DefaultConversionPropertiesProcessor Conversion registration error
 java.lang.NullPointerException
    at org.apache.struts2.cdi.CdiObjectFactory.getInjectionTarget(CdiObjectFactory.java:175)
    at org.apache.struts2.cdi.CdiObjectFactory.buildBean(CdiObjectFactory.java:148)
    at com.opensymphony.xwork2.ObjectFactory.buildBean(ObjectFactory.java:177)
    at com.opensymphony.xwork2.conversion.impl.DefaultTypeConverterCreator.createTypeConverter(DefaultTypeConverterCreator.java:40)
    at com.opensymphony.xwork2.conversion.impl.DefaultConversionPropertiesProcessor.loadConversionProperties(DefaultConversionPropertiesProcessor.java:86)
    at com.opensymphony.xwork2.conversion.impl.DefaultConversionPropertiesProcessor.processRequired(DefaultConversionPropertiesProcessor.java:68)
    at com.opensymphony.xwork2.conversion.impl.DefaultConversionPropertiesProcessor.init(DefaultConversionPropertiesProcessor.java:59)
    at com.opensymphony.xwork2.inject.InitializableFactory.create(InitializableFactory.java:45)
    at com.opensymphony.xwork2.inject.Scope.create(Scope.java:52)
    at com.opensymphony.xwork2.inject.ContainerBuilder.create(ContainerBuilder.java:118)
    at com.opensymphony.xwork2.inject.ContainerBuilder.call(ContainerBuilder.java:626)
    at com.opensymphony.xwork2.inject.ContainerBuilder.call(ContainerBuilder.java:623)
    at com.opensymphony.xwork2.inject.ContainerImpl.callInContext(ContainerImpl.java:555)
    at com.opensymphony.xwork2.inject.ContainerBuilder.create(ContainerBuilder.java:623)
    at com.opensymphony.xwork2.config.impl.DefaultConfiguration.reloadContainer(DefaultConfiguration.java:187)
    at com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:66)
    at org.apache.struts2.dispatcher.Dispatcher.getContainer(Dispatcher.java:957)
    at org.apache.struts2.dispatcher.Dispatcher.init_PreloadConfiguration(Dispatcher.java:463)
    at org.apache.struts2.dispatcher.Dispatcher.init(Dispatcher.java:496)
    at org.apache.struts2.util.StrutsTestCaseHelper.initDispatcher(StrutsTestCaseHelper.java:44)
    at org.apache.struts2.StrutsTestCase.initDispatcher(StrutsTestCase.java:236)
    at org.apache.struts2.StrutsTestCase.setUp(StrutsTestCase.java:216)
    at com.xxxx.xxxxx.xx.xxx.PasswordActionTest.setUp(PasswordActionTest.java:31)
    at junit.framework.TestCase.runBare(TestCase.java:139)
    at junit.framework.TestResult.protect(TestResult.java:122)
    at junit.framework.TestResult.runProtected(TestResult.java:142)
    at junit.framework.TestResult.run(TestResult.java:125)
    at junit.framework.TestCase.run(TestCase.java:129)
    at junit.framework.TestSuite.runTest(TestSuite.java:255)
    at junit.framework.TestSuite.run(TestSuite.java:250)
    at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:84)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
ERROR DefaultConversionPropertiesProcessor Conversion registration error
 java.lang.NullPointerException
    at org.apache.struts2.cdi.CdiObjectFactory.getInjectionTarget(CdiObjectFactory.java:175)
    at org.apache.struts2.cdi.CdiObjectFactory.buildBean(CdiObjectFactory.java:148)
    at com.opensymphony.xwork2.ObjectFactory.buildBean(ObjectFactory.java:177)
    at com.opensymphony.xwork2.conversion.impl.DefaultTypeConverterCreator.createTypeConverter(DefaultTypeConverterCreator.java:40)
    at com.opensymphony.xwork2.conversion.impl.DefaultConversionPropertiesProcessor.loadConversionProperties(DefaultConversionPropertiesProcessor.java:86)
    at com.opensymphony.xwork2.conversion.impl.DefaultConversionPropertiesProcessor.process(DefaultConversionPropertiesProcessor.java:64)
    at com.opensymphony.xwork2.conversion.impl.DefaultConversionPropertiesProcessor.init(DefaultConversionPropertiesProcessor.java:60)
    at com.opensymphony.xwork2.inject.InitializableFactory.create(InitializableFactory.java:45)
    at com.opensymphony.xwork2.inject.Scope.create(Scope.java:52)
    at com.opensymphony.xwork2.inject.ContainerBuilder.create(ContainerBuilder.java:118)
    at com.opensymphony.xwork2.inject.ContainerBuilder.call(ContainerBuilder.java:626)
    at com.opensymphony.xwork2.inject.ContainerBuilder.call(ContainerBuilder.java:623)
    at com.opensymphony.xwork2.inject.ContainerImpl.callInContext(ContainerImpl.java:555)
    at com.opensymphony.xwork2.inject.ContainerBuilder.create(ContainerBuilder.java:623)
    at com.opensymphony.xwork2.config.impl.DefaultConfiguration.reloadContainer(DefaultConfiguration.java:187)
    at com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:66)
    at org.apache.struts2.dispatcher.Dispatcher.getContainer(Dispatcher.java:957)
    at org.apache.struts2.dispatcher.Dispatcher.init_PreloadConfiguration(Dispatcher.java:463)
    at org.apache.struts2.dispatcher.Dispatcher.init(Dispatcher.java:496)
    at org.apache.struts2.util.StrutsTestCaseHelper.initDispatcher(StrutsTestCaseHelper.java:44)
    at org.apache.struts2.StrutsTestCase.initDispatcher(StrutsTestCase.java:236)
    at org.apache.struts2.StrutsTestCase.setUp(StrutsTestCase.java:216)
    at com.xxx.xxxx.xxx.xxxx.PasswordActionTest.setUp(PasswordActionTest.java:31)
    at junit.framework.TestCase.runBare(TestCase.java:139)
    at junit.framework.TestResult.protect(TestResult.java:122)
    at junit.framework.TestResult.runProtected(TestResult.java:142)
    at junit.framework.TestResult.run(TestResult.java:125)
    at junit.framework.TestCase.run(TestCase.java:129)
    at junit.framework.TestSuite.runTest(TestSuite.java:255)
    at junit.framework.TestSuite.run(TestSuite.java:250)
    at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:84)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

这之后,即使报错了,我也可以继续测试,比如下面的测试:

@Test
public void testGetActionProxy() throws Exception {

    //set parameters before calling getActionProxy
    PasswordUpdate pu = new PasswordUpdate();
    pu.setCurrentPassword("current");
    pu.setNewPassword("new");
    pu.setNewPasswordConfirm("new");
    request.setParameter("passwordUpdate.currentPassword", pu.getCurrentPassword());
    request.setParameter("passwordUpdate.newPassword", pu.getNewPassword());
    request.setParameter("passwordUpdate.newPasswordConfirm", pu.getNewPasswordConfirm());

    ActionProxy proxy = getActionProxy("/UpdatePassword.action");
    assertNotNull(proxy);

    PasswordAction action = (PasswordAction) proxy.getAction();
    assertNotNull(action);

    String result = proxy.execute();
    assertEquals(Action.SUCCESS, result);
    assertNotNull(action.getPasswordUpdate());
    assertEquals("current", action.getPasswordUpdate().getCurrentPassword());
    assertEquals("new", action.getPasswordUpdate().getNewPassword());
    assertEquals("new", action.getPasswordUpdate().getNewPasswordConfirm());

}

第二个问题是调用时好像没有找到action:

ActionProxy proxy = getActionProxy("/UpdatePassword.action");

它在 getActionProxy 中抛出异常:

protected ActionProxy getActionProxy(String uri) {
        request.setRequestURI(uri);
        ActionMapping mapping = getActionMapping(request);
        String namespace = mapping.getNamespace();
        String name = mapping.getName();
        String method = mapping.getMethod();

        Configuration config = configurationManager.getConfiguration();
        ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(
                namespace, name, method, new HashMap<String, Object>(), true, false);

        initActionContext(proxy.getInvocation().getInvocationContext());

        // this is normally done in onSetUp(), but we are using Struts internal
        // objects (proxy and action invocation)
        // so we have to hack around so it works
        ServletActionContext.setServletContext(servletContext);
        ServletActionContext.setRequest(request);
        ServletActionContext.setResponse(response);

        return proxy;
    }

此时字符串方法为空,下面的调用抛出异常:

ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy( namespace, name, method, new HashMap(), true, false);

在我放弃之前有什么想法吗?

谢谢!

以防其他人遇到同样的问题post

ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console...
ERROR CdiObjectFactory [findBeanManager]: Could not find BeanManager instance for any given JNDI key, giving up
ERROR CdiObjectFactory Struts2 CDI integration could not be initialized.
ERROR DefaultConversionPropertiesProcessor Conversion registration error

您可以通过从配置中排除 struts2-cdi-plugin

来解决这个问题