99

首先,我在 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

4

7 回答 7

146

只需@Transactional在测试顶部添加注释:

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

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

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

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

于 2012-09-27T17:08:55.587 回答
19

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

此编辑不会使帖子更易于阅读、更易于查找、更准确或更易于访问。更改要么完全是多余的,要么会严重损害可读性。


指向有关集成测试的文档相关部分的正确且永久的链接。

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

@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,则该类层次结构中的每个测试方法都将在事务中运行。

于 2016-03-11T15:14:06.440 回答
14

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

于 2012-09-27T17:40:31.560 回答
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" />

希望能帮助到你。

于 2016-01-19T06:56:47.807 回答
3

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

于 2020-08-18T06:47:33.757 回答
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
     }
}

有关详细信息,请参阅 Spring 参考章节3.5.8. Transaction Management

于 2012-09-27T17:04:44.717 回答
-7

您可以禁用回滚:

@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();
    }
}
于 2016-01-04T09:47:43.950 回答