@Test之后的回滚事务


85

首先,我在StackOverflow上找到了很多与此相关的线程,但是它们都没有真正帮助我,因此很抱歉提出可能重复的问题。

我正在使用spring-test运行JUnit测试,我的代码如下所示

@RunWith(SpringJUnit4ClassRunner.class)  
@ContextConfiguration(locations = {})
public class StudentSystemTest {

    @Autowired
    private StudentSystem studentSystem;

    @Before
    public void initTest() {
    // set up the database, create basic structure for testing
    }

    @Test
    public void test1() {
    }    
    ...  
}

我的问题是我希望我的测试不影响其他测试。所以我想为每个测试创建类似回滚的东西。我为此进行了很多搜索,但到目前为止我什么都没找到。我为此使用Hibernate和MySql


回滚是什么意思?清理数据库?
Gaurav 2012年

5
将其设置为与执行后完全相同的状态initTest
Jan Vorcak 2012年

Answers:


127

只需@Transactional在测试之上添加注释:

@RunWith(SpringJUnit4ClassRunner.class)  
@ContextConfiguration(locations = {"testContext.xml"})
@Transactional
public class StudentSystemTest {

默认情况下,Spring将启动围绕您的测试方法和@Before/@After回调的新事务,并在最后回滚。默认情况下它起作用,在上下文中有一些事务管理器就足够了。

来自:10.3.5.4事务管理(粗体):

在TestContext框架中,事务由TransactionalTestExecutionListener进行管理。请注意,即使您未在测试类上显式声明,它TransactionalTestExecutionListener也是默认配置的@TestExecutionListeners。但是,要启用对事务的支持,必须PlatformTransactionManager在由@ContextConfiguration语义加载的应用程序上下文中提供一个bean 。此外,您必须@Transactional在类或方法级别为测试声明


2
好吧,我之前曾尝试过,但仍然无法正常工作,也许...问题可能是我没有定义PlatformTransactionManager,我该怎么做?
Jan Vorcak 2012年

@javo:您如何修改数据库?如果您使用的是Jpa / Hibernate / JdbcTemplate / ...,则必须有一些PlatformTransactionManager。否则,Spring将如何了解您的事务和数据库?
Tomasz Nurkiewicz 2012年

1
此答案中的链接不再正确;请参阅下面的user2418306的答案以获取正确的链接和Spring文档中的更多上下文。
DaveyDaveDave

1
我不工作,每种方法都需要一个单独的事务,不能全班使用
Kamil Nekanowicz

我正在测试插入到表中。使用@Transactional时,甚至不会针对数据库发出insert命令(我可以看到这是因为控制台具有休眠的show-sql true)。在许多情况下都能正常工作。但是我的测试之一检查由于数据库约束数据库是否发出DataAccessException。在这种情况下,测试将失败,因为回滚发生在“内存中”,并且永远不会调用数据库。解决方案:@Transactional@Test方法级别而非类级别使用。
Paulo Merson

17

撇开试图修改托马斯·努尔基维茨的答案被拒绝了:

此修改并不会使帖子更易于阅读,更容易找到,更准确或更易于访问。更改完全是多余的,或者会严重损害可读性。


正确和永久链接到有关集成测试的文档的相关部分。

要启用对事务的支持,必须在中配置一个通过语义加载的PlatformTransactionManagerbean 。ApplicationContext@ContextConfiguration

@组态
@PropertySource(“ application.properties”)
公共类持久性{
    @Autowired
    环境环境

    @豆角,扁豆
    数据源dataSource(){
        返回新的DriverManagerDataSource(
                env.getProperty(“ datasource.url”),
                env.getProperty(“ datasource.user”),
                env.getProperty(“ datasource.password”)
        );
    }

    @豆角,扁豆
    PlatformTransactionManager transactionManager(){
        返回新的DataSourceTransactionManager(dataSource());
    }
}

另外,您必须@Transactional在类或方法级别为测试声明Spring的批注。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {Persistence.class,SomeRepository.class})
@交易
公共类SomeRepositoryTest {...}

使用注释测试方法将@Transactional导致测试在事务中运行,默认情况下,该事务将在测试完成后自动回滚。如果用注释了测试类,则@Transactional该类层次结构中的每个测试方法都将在事务中运行。


12

提到添加的答案@Transactional是正确的,但是为简单起见,您可以只具有test类extends AbstractTransactionalJUnit4SpringContextTests


1
在类级别添加注释'@Transactional'不起作用,为每个函数分别添加注释'@Transactional'并扩展AbstractTransactionalJUnit4SpringContextTests也起作用
Kamil Nekanowicz

5

我知道,我迟到发布答案了,但是希望它能对某人有所帮助。另外,我刚刚解决了测试中遇到的这个问题。这是我在测试中得到的:

我的考试课

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "path-to-context" })
@Transactional
public class MyIntegrationTest 

上下文XML

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
   <property name="driverClassName" value="${jdbc.driverClassName}" />
   <property name="url" value="${jdbc.url}" />
   <property name="username" value="${jdbc.username}" />
   <property name="password" value="${jdbc.password}" />
</bean>

我仍然有一个问题,数据库没有自动清理。

当我将以下属性添加到BasicDataSource时,问题已解决

<property name="defaultAutoCommit" value="false" />

希望能帮助到你。


那么,您是手动提交语句吗?您确定您的数据甚至已写入数据库中吗?
franta kocourek

对于任何想了解Spring Transactions的人来说,请确保您的数据源未设置为自动提交,否则您将疯狂地尝试弄清楚@Transactional为什么不起作用。
乔·恩斯特

2

您需要使用Spring上下文和事务管理器来运行测试,例如,

@RunWith(SpringJUnit4ClassRunner.class)  
@ContextConfiguration(locations = {"/your-applicationContext.xml"})
@TransactionConfiguration(transactionManager="txMgr")
public class StudentSystemTest {

     @Test
     public void testTransactionalService() {
         // test transactional service
     }

     @Test
     @Transactional
     public void testNonTransactionalService() {
         // test non-transactional service
     }
}

有关3.5.8. Transaction Management更多详细信息,请参见Spring参考中的章节。


0

除了增加@Transactional@Test方法,您还需要添加@Rollback(false)


-4

您可以禁用回滚:

@TransactionConfiguration(defaultRollback = false)

例:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@Transactional
@TransactionConfiguration(defaultRollback = false)
public class Test {
    @PersistenceContext
    private EntityManager em;

    @org.junit.Test
    public void menge() {
        PersistentObject object = new PersistentObject();
        em.persist(object);
        em.flush();
    }
}

6
这正是在OP是要求相反
亚当·米哈利克

这应该是对已接受答案的评论。
DerMike
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.