一尘不染

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

hibernate

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

我正在使用@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。为什么回滚被忽略?


阅读 265

收藏
2020-06-20

共1个答案

一尘不染

您需要将事务范围扩展到测试方法的范围。您可以通过将测试方法(或整个测试类)注释为@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 ... ); 
}
2020-06-20