测试action,见http://blog.csdn.net/jazywoo123/article/details/8267208
但是写测试用例时,
package bijian.controller.action;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.http.HttpSession;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.mock.web.MockHttpSession;
import com.opensymphony.xwork2.Action;
import bijian.model.bean.Label;
import bijian.model.bean.Sentence;
import bijian.model.bean.User;
public class PageActionTests extends ActionTestBase{
public void testDisplayHomepage() throws Exception{
// User user=new User();
// user.setUserID(100);
// user.setUsername("jazywoo");
// this.request.getSession().putValue("loginUser", user);
String result=this.executeAction("/pageAction!displayHomepage.action");
//Assert.assertEquals(Action.SUCCESS,result);
Map resultMap=(Map) findValueAfterExecute("resultMap");
List<User> hotUserList=(List<User>) resultMap.get("homepage_hotUserList");
List<Sentence> sentenceList=(List<Sentence>) resultMap.get("homepage_sentenceList");
List<Label> hotLabelList=(List<Label>) resultMap.get("homepage_hotLabelList");
System.out.println(hotUserList.get(0).getNickname());
// System.out.println(sentenceList.get(0).getContent());
// System.out.println(hotLabelList.get(0).getContent());
}
public void testDisplayUserHomepage() throws Exception{
User user=new User();
user.setUserID(100);
user.setUsername("jazywoo");
HttpSession session=new MockHttpSession();
// String sessionID=UUID.randomUUID().toString();
// session.setAttribute(ConstParameter.USER_SESSION, sessionID);
session.putValue("loginUser", user);
this.request.setSession(session);
String result=this.executeAction("/pageAction!displayUserHomepage.action");
//Assert.assertEquals(Action.SUCCESS,result);
Map resultMap=(Map) findValueAfterExecute("resultMap");
String userHomePage_type=(String) resultMap.get("userHomePage_type");
Assert.assertEquals("suggest", userHomePage_type);
}
}
会报错
java.lang.IllegalStateException: Already value [org.springframework.orm.hibernate3.SessionHolder@6a4d1a] for key [org.hibernate.impl.SessionFactoryImpl@4bd173] bound to thread [main]
at org.springframework.transaction.support.TransactionSynchronizationManager.bindResource(TransactionSynchronizationManager.java:189)
at bijian.controller.action.ActionTestBase.setUp(ActionTestBase.java:27)
at junit.framework.TestCase.runBare(TestCase.java:132)
at junit.framework.TestResult$1.protect(TestResult.java:110)
at junit.framework.TestResult.runProtected(TestResult.java:128)
at junit.framework.TestResult.run(TestResult.java:113)
at junit.framework.TestCase.run(TestCase.java:124)
at junit.framework.TestSuite.runTest(TestSuite.java:232)
at junit.framework.TestSuite.run(TestSuite.java:227)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:79)
at ...............................
主要是
java.lang.IllegalStateException: Already value [org.springframework.orm.hibernate3.SessionHolder@6a4d1a] for key [org.hibernate.impl.SessionFactoryImpl@4bd173] bound to thread
使用StrutsSpringTestCase 测试时, TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));的理解如下:
在调用一个需要事务的组件的时候,管理器首先判断当前调用(即当前线程)有没有一个事务,如果没有事务则启动一个事务,并把事务与当前线程绑定。Spring使用TransactionSynchronizationManager的bindResource方法将当前线程与一个事务绑定,采用的方式就是ThreadLocal,
@Override
protected void setUp() throws Exception {
super.setUp();
SessionFactory sessionFactory = lookupSessionFactory(this.request);
Session hibernateSession= getSession(sessionFactory);
TransactionSynchronizationManager.bindResource(sessionFactory,new SessionHolder(hibernateSession));
}
private Session getSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException {
Session session = SessionFactoryUtils.getSession(sessionFactory, true);
FlushMode flushMode = FlushMode.NEVER;
if (flushMode != null) {
session.setFlushMode(flushMode);
}
return session;
}
private SessionFactory lookupSessionFactory(HttpServletRequest request) {
//“sessionFactory”是你spring配置文件(通常是application.xml)中的SessionFactory。
//如:org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean
return (SessionFactory)this.applicationContext.getBean("sessionFactory");
}
而测试时,有多个用例,相当于请求多次,hibernate的session再次关联到线程,因而会报错java.lang.IllegalStateException: Already value [org.springframework.orm.hibernate3.SessionHolder@6a4d1a] for key [org.hibernate.impl.SessionFactoryImpl@4bd173] bound to thread
我解决的方式是,在异常处使用try catch语句,如果是抛出的异常,则不再将session关联到线程
package bijian.controller.action;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.StrutsSpringTestCase;
import org.hibernate.FlushMode;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.orm.hibernate3.SessionFactoryUtils;
import org.springframework.orm.hibernate3.SessionHolder;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import bijian.controller.action.UserAction;
public class ActionTestBase extends StrutsSpringTestCase {
/*这个函数相当@Before注解的函数,是调用单元测试后的时候,
首先会执行的方法。可以在这里面做一些必要的准备工作*/
@Override
protected void setUp() throws Exception {
super.setUp();
SessionFactory sessionFactory = lookupSessionFactory(this.request);
Session hibernateSession= getSession(sessionFactory);
try{
TransactionSynchronizationManager.bindResource(sessionFactory,new SessionHolder(hibernateSession));
}catch(IllegalStateException e){
//e.printStackTrace();
//session已经关联存在,不再将session关联到线程
}
}
@Override
public String getContextLocations() {
//返回你项目中spring配置文件所在的目录
return "/spring.xml";
}
private Session getSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException {
Session session = SessionFactoryUtils.getSession(sessionFactory, true);
FlushMode flushMode = FlushMode.NEVER;
if (flushMode != null) {
session.setFlushMode(flushMode);
}
return session;
}
private SessionFactory lookupSessionFactory(HttpServletRequest request) {
//“sessionFactory”是你spring配置文件(通常是application.xml)中的SessionFactory。
//如:org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean
return (SessionFactory)this.applicationContext.getBean("sessionFactory");
}
}