为什么交易不会在我的junit测试用例中开始?

时间:2012-07-15 12:27:17

标签: spring hibernate junit spring-transactions spring-annotations

我有一个带有junit4测试套件的Spring 3.1 MVC + Hibernate 3.6项目。我的问题是我的测试用例中没有开始交易,甚至认为我添加了 @Transactional

我的测试用例调用了一个控制器和一个dao。在控制器中,无论如何都要启动一个事务,所以它不会抱怨。在dao中,我添加了一个 @Transactional(propagation = Propagation.MANDATORY)以确保它将进行测试的事务。目前它引发了一个 IllegalTransactionStateException ,我想这意味着没有当前的交易。

我尝试创建一个programmaticaly一个事务,它确实有效,这意味着获取dao服务的AOP代理不是问题的原因。但是,我想使用 @Transactional 注释创建一个事务。

这是我的道:

// ...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的文档中搜索并用我能想象的任何方式搜索它,但我不明白为什么交易没有开始。 非常欢迎任何帮助。

1 个答案:

答案 0 :(得分:13)

使用@RunWith(SpringJUnit4ClassRunner.class)时,您应该从SpringJUnit4ClassRunner而不是您自己的应用程序上下文中获取bean。

在您的情况下出现问题,因为单元测试上的@Transactional在由SpringJUnit4ClassRunner管理的应用程序上下文中创建了一个事务,但您调用从手动创建的应用程序上下文获取的bean上的方法。 / p>

因此,请移除您的@BeforeClass方法并通过自动装配获取TaskDao

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "/test-config.xml", "/applicationContext.xml" })  
@TransactionConfiguration(defaultRollback = true)
@Transactional  
public class TestTaskController {
    @Autowired
    private TaskDao taskDao; 

    ...
}

另见: