我正在通过测试驱动开发(TDD)将旧的 Struts 1 应用程序与 Spring 3 集成在一起。出于这个原因,我的集成测试非常重要。我正在尝试使用“Struts测试用例”来实现动作的集成测试。 操作(HomeAction)是自动装配,带有单件服务和会话bean (篮子)。 但是当我运行测试时,我收到以下错误:
创建名为'scopedTarget.basket'的bean时出错:范围'session' 当前线程不活动;考虑定义范围代理 对于这个bean,如果你打算从单身中引用它;嵌套 异常是java.lang.IllegalStateException:没有线程绑定请求 发现:您是指实际的请求属性吗? Web请求,或处理原始请求之外的请求 接收线程?如果您实际在Web请求中操作 并且仍然收到此消息,您的代码可能正在外面运行 DispatcherServlet / DispatcherPortlet:在这种情况下,请使用 RequestContextListener或RequestContextFilter公开当前 请求。
注入服务但会话bean没有注入。 如果我尝试运行该应用程序,它可以正常工作。
有人知道如何解决它吗?我不知道它是否是maven配置问题,但似乎通过测试,Web上下文没有像应用程序执行时那样加载。 提前谢谢。
这是代码:
Web.xml中
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>
org.apache.struts.action.ActionServlet
</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>
/WEB-INF/struts-config.xml
</param-value>
</init-param>
<init-param>
<param-name>autowire</param-name>
<param-value>byName</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
的struts-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
"http://struts.apache.org/dtds/struts-config_1_3.dtd">
<struts-config>
<!-- ========== Definiciones de Form Bean =================== -->
<form-beans>
<form-bean name="homeForm" type="org.examples.appname.web.action.HomeForm" />
</form-beans>
<!-- ==========Forward's Globales ============================== -->
<global-forwards>
<forward name="error" path="/WEB-INF/views//error.jsp" />
</global-forwards>
<!-- ========== Mapeo de Acciones ============================== -->
<action-mappings>
<action path="/" type="org.apache.struts.actions.ForwardAction" parameter="/home"/>
<action path="/home" type="org.examples.appname.web.action.HomeAction" name="homeForm" scope="request">
<forward name="success" path="/WEB-INF/views/home.jsp" />
</action>
</action-mappings>
<!-- ========== Controller Configuration ======================== -->
<controller>
<!-- Autowaring injection of actions: You don't need to declare them on action-servlet.xml -->
<set-property property="processorClass" value="org.springframework.web.struts.AutowiringRequestProcessor" />
</controller>
<!-- ========== Message Resources Definitions ==================== -->
<message-resources parameter="org.example.appname.ApplicationResources" />
<!-- ========== Plugins configuration ==================== -->
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation" value="/WEB-INF/action-servlet.xml, /WEB-INF/root-context.xml"/>
</plug-in>
</struts-config>
action-servlet.xml为空,因为操作是自动装配的。
<!-- Action Context: defines all web actions -->
<beans></beans>
Spring Context:root-context.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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<context:annotation-config/>
<context:component-scan base-package="org.examples.appname" scoped-proxy="targetClass"/>
<bean name="MenuService" class="org.examples.appname.core.service.MenuServiceImpl" scope="singleton"/>
</beans>
HomeAction.java
@Component
public class HomeAction extends LookupDispatchAction {
@Autowired
private Basket basket;
private MenuService menuService;
public void setMenuService(MenuService menuService) {
this.menuService = menuService;
System.out.println(this.toString() + " - " + this.menuService.toString());
}
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
ActionErrors errors = new ActionErrors();
HttpSession session = request.getSession();
System.out.println("request " + request.hashCode());
System.out.println("Session " + session.getId() + " - " + new Date(session.getCreationTime()));
System.out.println("Basket " + basket.getState());
//store an object on the request
request.setAttribute("MenuItems", menuService.getMenuItems());
// Forward control to the specified success URI
return mapping.findForward("success");
}
@Override
protected Map getKeyMethodMap() {
// TODO Auto-generated method stub
return null;
}
}
Basket.java
@Component
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class Basket{
private final String state;
public Basket() {
this.state = UUID.randomUUID().toString();
}
public String getState() {
return state;
}
}
HomeIntegrationTest.java
public class HomeIntegrationTest extends MockStrutsTestCase{
private static final String FORWARDED_URL = "/home";
private static final String VIEW = "/WEB-INF/views/home.jsp";
@Before
public void setUp() throws Exception {
super.setUp();
}
@Test
public void testIndexUrlforwardsCorrectly() throws Exception {
setRequestPathInfo("/");
actionPerform();
verifyForwardPath(FORWARDED_URL);
verifyNoActionErrors();
}
@Test
public void testHomeUrlforwardsCorrectly() throws Exception {
setRequestPathInfo("/home");
actionPerform();
verifyForwardPath(VIEW);
assertEquals("Menu items", getRequest().getAttribute("MenuItems"));
verifyNoActionErrors();
}
}
Maven pom.xml
<testResources>
<testResource>
<directory>src/test/java</directory>
<includes>
<include>*.*</include>
</includes>
</testResource>
<testResource>
<directory>src/main/webapp/WEB-INF</directory>
<targetPath>/WEB-INF</targetPath> -->
<includes>
<include>*.xml</include>
</includes>
</testResource>
</testResources>
答案 0 :(得分:0)
很久以前我写过一篇关于使用Maven对struts应用程序进行单元测试的博客。我不想在这里复制整个故事,而是提到JUnit test Struts applications with mock objects and Maven。我希望它有所帮助。
答案 1 :(得分:0)
正如我上面所说的,我在这个link之后解决了它并添加到spring bean xml(root-context.xml)这个bean,
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="session">
<bean class="org.springframework.context.support.SimpleThreadScope"/>
</entry>
</map>
</property>
</bean>
但是我在执行环境中得到了以下警告:
'SimpleThreadScope不支持销毁回调。考虑 在Web环境中使用RequestScope。'
为了允许此消息进行测试,我通过maven pom.xml为测试环境设置了不同的spring上下文xml(root-context.xml)。
<build>
<testResources>
<testResource>
<directory>src/main/webapp/WEB-INF</directory>
<targetPath>/WEB-INF</targetPath>
<includes>
<include>*.xml</include>
</includes>
<excludes>
<exclude>root-context.xml</exclude>
</excludes>
</testResource>
<testResource>
<directory>src/test/webapp/WEB-INF</directory>
<targetPath>/WEB-INF</targetPath>
<includes>
<include>*.xml</include>
</includes>
</testResource>
</testResources>
</build>