@Test之后的回滚事务

Jan*_*cak 69 java junit spring hibernate spring-test

首先,我在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() {
    }    
    ...  
}
Run Code Online (Sandbox Code Playgroud)

我的问题是我希望我的测试不会影响其他测试.所以我想为每个测试创建类似回滚的东西.我为此搜索了很多,但到目前为止我一无所获.我正在使用Hibernate和MySql

Tom*_*icz 115

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

@RunWith(SpringJUnit4ClassRunner.class)  
@ContextConfiguration(locations = {"testContext.xml"})
@Transactional
public class StudentSystemTest {
Run Code Online (Sandbox Code Playgroud)

默认情况下,Spring将启动围绕测试方法和@Before/ @After回调的新事务,最后回滚.它默认工作,它足以在上下文中有一些事务管理器.

来自:10.3.5.4交易管理(大胆矿):

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

  • 好吧,我之前曾尝试过,但仍然无法正常工作,也许...问题可能是我没有定义PlatformTransactionManager,我该怎么做? (2认同)
  • 此答案中的链接不再正确;有关 Spring 文档中的正确链接和更多上下文,请参阅 [user2418306's answer below](http://stackoverflow.com/a/35943700/325900)。 (2认同)

use*_*306 15

旁白:试图修改Tomasz Nurkiewicz的答案被拒绝:

此编辑不会使帖子更容易阅读,更容易找到,更准确或更容易访问.变化要么完全是多余的,要么是主动损害可读性.


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

要启用对事务的支持,必须PlatformTransactionManagerApplicationContext通过@ContextConfiguration语义加载的bean中配置bean .

@Configuration
@PropertySource("application.properties")
public class Persistence {
    @Autowired
    Environment env;

    @Bean
    DataSource dataSource() {
        return new DriverManagerDataSource(
                env.getProperty("datasource.url"),
                env.getProperty("datasource.user"),
                env.getProperty("datasource.password")
        );
    }

    @Bean
    PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }
}

此外,您必须@Transactional在测试的类或方法级别声明Spring的注释.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {Persistence.class, SomeRepository.class})
@Transactional
public class SomeRepositoryTest { ... }

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


mat*_*t b 12

提到添加的答案@Transactional是正确的,但为了简单起见,您可以使用您的测试类extends AbstractTransactionalJUnit4SpringContextTests.

  • 在类级别添加注释“@Transactional”不起作用,为每个函数单独添加注释“@Transactional”有效,并且扩展 AbstractTransactionalJUnit4SpringContextTests 也有效 (3认同)

小智 6

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

  • 这回答了相反的问题,即如何在测试中“不回滚”事务。但知道这仍然很高兴,这就是我来寻找的。 (8认同)

Atu*_*har 5

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

我的测试班

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

上下文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>
Run Code Online (Sandbox Code Playgroud)

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

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

<property name="defaultAutoCommit" value="false" />
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你。

  • 对于任何难以理解 Spring Transactions 的人,请确保您的数据源未设置为自动提交,否则您会发疯地试图弄清楚为什么 @Transactional 似乎什么都不做。 (2认同)