在JUnit中使用Spring测试服务时如何回滚数据库事务?

时间:2010-11-12 16:45:23

标签: java hibernate spring transactions junit

测试我的DAO和服务没有问题,但是当我测试INSERTUPDATE时,我想回滚事务而不影响我的数据库。

我在我的服务中使用@Transactional来管理交易。我想知道,是否有可能知道某个事务是否正常,但是回滚它以防止更改数据库?

这是我的测试:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:/META-INF/spring.cfg.xml")
@TransactionConfiguration(defaultRollback=true)
public class MyServiceTest extends AbstractJUnit38SpringContextTests  {
    @Autowired
    private MyService myService;

    @BeforeClass
    public static void setUpClass() throws Exception {
    }

    @AfterClass
    public static void tearDownClass() throws Exception {
    }

    @Test
    public void testInsert(){
        long id = myService.addPerson( "JUNIT" );
        assertNotNull( id );
        if( id < 1 ){
            fail();
        }
    }
}

问题是此测试将失败,因为事务已回滚,但插入正常! 如果我删除@TransactionConfiguration(defaultRollback=true)然后测试通过,但新记录将被插入数据库。

@Test
@Transactional
@Rollback(true)
public void testInsert(){
    long id = myService.addPerson( "JUNIT" );
assertNotNull(id);
if( id < 1 ){
        fail();
    }
}

现在可以正确测试传递,但忽略回滚并将记录插入数据库。 很明显,我已经使用addPerson()在myService中注释了@Transactional方法。 为什么忽略回滚?

4 个答案:

答案 0 :(得分:30)

您需要将事务边界扩展到测试方法的边界。您可以通过将测试方法(或整个测试类)注释为@Transactional

来实现
@Test 
@Transactional
public void testInsert(){ 
    long id=myService.addPerson("JUNIT"); 
    assertNotNull(id); 
    if(id<1){ 
        fail(); 
    } 
} 

您还可以使用此方法确保在回滚之前正确写入数据:

@Autowired SessionFactory sf;

@Test 
@Transactional
public void testInsert(){ 
    myService.addPerson("JUNIT"); 
    sf.getCurrentSession().flush();
    sf.getCurrentSession().doWork( ... check database state ... ); 
} 

答案 1 :(得分:2)

结帐

http://static.springsource.org/spring/docs/2.5.x/reference/testing.html

特别是第8.3.4节

Spring有一些测试类可以将每个测试包装在一个事务中,因此DB不会被更改。如果您愿意,也可以更改该功能。

编辑 - 根据您的更多信息,您可能需要查看

AbstractTransactionalJUnit38SpringContextTests at

http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/test/context/junit38/AbstractTransactionalJUnit38SpringContextTests.html

答案 2 :(得分:1)

在课前使用以下注释:

@TransactionConfiguration(transactionManager = "txManager",defaultRollback = true)
@Transactional

此处txManager是应用程序上下文的事务管理器。

此处txManager是来自application context的事务管理器的实例或bean ID。

<!-- Transaction Manager -->
    <bean id="txManager"
          class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <tx:annotation-driven transaction-manager="txManager" />

setUp()方法中添加代码,这将在测试开始时执行,最后一个代码应该放在最后执行的teatDown()方法中。或者您也可以使用@Before@After注释代替它。

答案 3 :(得分:0)

如果你的

myService.addPerson("JUNIT"); 

方法注释为@Transactional,你会得到一些不同的类型或错误试图解决这个问题。所以你最好只测试DAO方法。