问题描述
我有一个带有junit4测试套件的Spring 3.1 MVC + Hibernate 3.6项目.我的问题是,即使我添加了 @Transactional .
I have a Spring 3.1 MVC + Hibernate 3.6 project with its junit4 test suit. My problem is that there is no transaction starting in my test cases, even thought I added a @Transactional.
我的测试用例调用一个控制器和一个dao.在控制器中,无论如何都开始事务,因此它不会抱怨.在dao中,我添加了一个 @Transactional(propagation = Propagation.MANDATORY),以确保它将接受测试的事务.当前,它引发一个 IllegalTransactionStateException ,我想这意味着没有当前交易.
My test case calls a controller and a dao. In the controller, a transaction is started anyway, so it does not complain. In the dao, I added a @Transactional(propagation = Propagation.MANDATORY) to be sure it will take the test's transaction. And currently it raises an IllegalTransactionStateException, which I guess it means there is no current transaction.
我试图以编程方式创建一个事务,并且该事务确实起作用,这意味着获取dao服务的AOP代理不是问题的起因.但是,我想使用 @Transactional 批注创建交易.
I tried to create programmaticaly an transaction and it does work, which means the AOP proxy to get the dao service is not the cause of the problem. However I want to create a transaction with the @Transactional annotation.
这是我的岛
// ...imports...
@Repository("taskDao")
@Transactional(propagation = Propagation.MANDATORY)
public class TaskHome implements TaskDao {
private static final Log log = LogFactory.getLog(TaskHome.class);
private SessionFactory sessionFactory;
@Autowired
public TaskHome(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public Task findById(int id) {
log.debug("getting Task instance with id: " + id);
try {
Task instance = (Task) this.sessionFactory.getCurrentSession().get(
Task.class, id); // exception raised here!
if (instance == null) {
log.debug("get successful, no instance found");
} else {
log.debug("get successful, instance found");
}
return instance;
} catch (RuntimeException re) {
log.error("get failed", re);
throw re;
}
}
...
}
这是我的测试用例:
// ...imports...
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "/test-config.xml", "/applicationContext.xml" })
@TransactionConfiguration(defaultRollback = true)
@Transactional
public class TestTaskController {
private static ClassPathXmlApplicationContext context;
private static TaskDao taskDao;
@BeforeClass
public static void initHibernate() throws Exception {
context = new ClassPathXmlApplicationContext("applicationContext.xml");
taskDao = context.getBean("taskDao", TaskDao.class);
}
@Test
public void testOnSubmit() {
// expects an existing default transaction here
Task task = taskDao.findById(1); // fails already here
// ... calls the controller and does some tests.
}
}
我搜索了所有Spring的文档,并以我能想到的任何方式对其进行了搜索,但是我不明白为什么交易没有开始.任何帮助都非常欢迎.
I searched in all Spring's documentation and googled it in any way I could imagine, but I don't see why the transaction is not started.Any help is very welcome.
推荐答案
使用@RunWith(SpringJUnit4ClassRunner.class)
时,应该从SpringJUnit4ClassRunner
创建的应用程序上下文中获取bean,而不是从自己的bean中获取bean.
When using @RunWith(SpringJUnit4ClassRunner.class)
you should obtain beans from the application context created by SpringJUnit4ClassRunner
rather than from your own one.
在您的情况下,事情会出错,因为单元测试中的@Transactional
在由SpringJUnit4ClassRunner
管理的应用程序上下文中创建了一个事务,但是您调用了从手动创建的应用程序上下文中获得的bean上的方法.
In your case things go wrong because @Transactional
on the unit test creates a transaction in the application context managed by SpringJUnit4ClassRunner
, but you call methods on the beans obtained from the application context created manually.
因此,删除您的@BeforeClass
方法并通过自动装配获得TaskDao
:
So, remove your @BeforeClass
method and obtain TaskDao
via autowiring:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "/test-config.xml", "/applicationContext.xml" })
@TransactionConfiguration(defaultRollback = true)
@Transactional
public class TestTaskController {
@Autowired
private TaskDao taskDao;
...
}
另请参见:
这篇关于为什么事务无法在我的junit测试用例中开始?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!