Junit测试用例中的saveorupdate调用不会引发正在进行的事务错误

时间:2019-05-29 17:18:12

标签: java spring hibernate junit

前提

我有一个带有Hibernate 5.4.1的Spring 5.1.5项目

编译进行得很好,但是在运行特定程序包的测试用例时,我看到多个测试失败。都有相同的错误:

  

java.lang.AssertionError           在com.project.server.package.dao.impl.SomeDAOImplTest.someTest(SomeDAOImplTest.java:105)

问题

现在,我知道Hibernate 5会强制执行事务检查,并且在这里找不到一个并引发异常。我的问题是,如果我有通过Spring上下文初始化的事务,为什么这样做呢?

我的测试用例:

@ContextConfiguration({ "classpath:/spring/applicationContext-package-dao--test.xml" })
public class SomeDAOImplTest extends AbstractDAOTest {

    @Autowired
    private SomeDAO someDAO;
    private className obj;

    @Before
    public void setUp() {
        obj = new ClassName();
        obj.setId(3);

        someDAO.saveOrUpdate(obj);
    }

我的applicationContext-package-dao--test.xml

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <import resource="classpath:/spring/applicationContext-persistence-datasource-test.xml" />
    <import resource="classpath:/spring/applicationContext-package-dao.xml" />

</beans>

导入的上下文applicationContext-persistence-datasource-test.xml具有如下的bean txProxyTemplate

<beans>
.
.//other beans
.
<bean id="txProxyTemplate" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="transactionManager" ref="transactionManager" />
    </bean>
<bean id="transactionManager" class="com.desktone.transaction.DtResourcelessTransactionManager" />
    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
.
.//other beans
.
</beans> 

另一个applicationContext-package-dao.xml具有SomeDAO作为其父代的txProxyTemplate的bean定义。

<bean id="SomeDAO" parent="txProxyTemplate">
        <property name="target">
            <bean class="com.project.server.package.dao.impl.SomeDAOImpl">
                <property name="sessionFactory" ref="sessionFactory" />
            </bean>
        </property>
        <property name="transactionAttributes">
            <props>
                <prop key="saveOrUpdate">PROPAGATION_REQUIRED</prop>
                <prop key="delete">PROPAGATION_REQUIRED</prop>
                <prop key="*">PROPAGATION_SUPPORTS,readOnly</prop>
            </props>
        </property>
</bean>

来自SomeDAOImplTest的saveorupdate调用调用了SomeDAOImpl,其弹簧上下文配置为applicationContext-package-dao.xml并具有休眠saveorupdate()调用。

我尝试过的事情:

  • 手动将@Transactional标记添加到SomeDAOImplTest。 (仍然不会发送任何TX错误)
  • 使用PROPAGATION.REQUIRES_NEW(仍然不会发送任何tx错误)和PROPAGATION.MANDATORY(表示为必需,但没有tx)进行实验。
  • 确保自动装配正在初始化bean。

主要怀疑

我怀疑以某种方式初始化someDAO bean,但没有初始化txProxyTemplate bean,因此没有transactionManager到位。但是,我没有找到佐证这一点的线索。

1 个答案:

答案 0 :(得分:0)

对我来说,这是由于一个非常基本的问题而发生的。我将解释这个问题,以后每个人都可以通过直观的方法来解决此问题。

当Spring应用程序运行时,所有bean都在单个/全局上下文中加载。因此,即使某些Spring bean配置依赖于事务bean(对我来说是txProxyTemplate),它在运行时不在同一个程序包中,也可以访问它。

但是,对于测试用例而言并非如此。我的测试报告没有正在进行的事务,因为它们无法加载txProxyTemplate并无法真正启动事务。因此,我的测试从未进行过交易,直到升级到Hibernate 5并对其施加了严格的约束后,我才知道更好。

您可能已经猜到在同一spring配置中定义txProxyTemplate可以帮助我解决此问题。

良好的学习。