2016-05-12 170 views
0

我想知道交易如何在春季工作,或多或少我已经学会了(或者我认为我已经学会了)。唯一没有得到的是如下:为了检查回滚如何实现它的魔力,我创建了一个测试,用@Transacional注释调用一个方法,该方法抛出一个异常,并查看方法更改是否从外部保存。令我惊讶的是,这一变化似乎已经付诸实施。春季交易方法测试不会回滚

这是代码:

import static org.hamcrest.core.IsNull.nullValue; 
import static org.junit.Assert.assertThat; 
import static org.junit.Assert.fail; 

import org.springframework.transaction.annotation.Transactional; 

import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.boot.test.SpringApplicationConfiguration; 
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 
import org.springframework.test.context.web.WebAppConfiguration; 

import repositories.files.ArchivoEnDisco; 
import repositories.files.ArchivosEnDiscoRepo; 

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = GhcserviceapiApplication.class) 
@WebAppConfiguration 
public class PruebasSinTransacciones { 

    @Autowired 
    ArchivosEnDiscoRepo repositorio; 

    @Test 
    public void compruebaTransaccionSinVariable() { 

     // I get one far away from the last. 
     Long id = repositorio.count() + 10l; 

     try { 

      inTransacction(id); 

      fail("Exception must be throw"); 

     } catch (Exception e) { 

     } 

     // I try to get the saved object 
     ArchivoEnDisco aedOriginal = repositorio.findOne(id); 

     assertThat("An exception ocurred so it doesn't have to find it", aedOriginal, nullValue()); 

    } 

    @Transactional() 
    private void inTransacction(Long id) throws Exception { 

     repositorio.save(new ArchivoEnDisco(id, id + "A.txt")); 

     throw new Exception(); 

    } 

} 

对于我来说,作为一个例外是抛出事务必须回滚,因此保存对象不需要在仓库中存在。但是当我运行测试时,find方法返回保存的对象。可能有人在我错了什么?


注:GhcserviceapiApplication@SpringBootApplication注释的类。 ArchivosEnDiscoRepoCrudRepository。我在我的pom中有spring-boot-starter-data-jpahsqldb,但jpa没有配置(所以我在内存中使用hsqldb)。


编辑

我分开,因为@M类。 Deinum评论,并试图使用和具体的rollbackFor参数,但结果是一样的。

// ConTransacciones.java 
// Also tried with Throwable.class 
@Transactional(rollbackFor=CustomError.class) 
public class ConTransacciones { 

    public ArchivosEnDiscoRepo repositorio; 

    public void enTransaccion(Long id) throws CustomError { 

     repositorio.save(new ArchivoEnDisco(id, id + "A.txt")); 

     throw new CustomError(); 

    } 

} 

// CustomError.java 
public class CustomError extends Exception { } 

// PruebasSinTransacciones.java 
@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = GhcserviceapiApplication.class) 
@WebAppConfiguration 
public class PruebasSinTransacciones { 

    @Autowired 
    ArchivosEnDiscoRepo repositorio; 

    @Test 
    public void compruebaTransaccionSinVariable() { 

     ConTransacciones ct = new ConTransacciones(); 
     ct.repositorio = this.repositorio; 

     Long id = repositorio.count() + 10l; 

     try { 

      ct.enTransaccion(id); 

      fail("Debería haberse lanzado una excepción"); 

     } catch (Exception e) { 

     } 

     ArchivoEnDisco aedOriginal = repositorio.findOne(id); 

     assertThat("La transacción no debería haber guardado el archivo", aedOriginal, nullValue()); 

    } 

} 
+0

这是一个内部方法调用,所以你的'@ Transactional'几乎没用。接下来,即使它不会工作,因为这不是'@ Transactional'在测试用例中的工作方式!此外,您并未测试与数据库相关的任何内容,因此您只测试一级缓存。最后,'@ Transactional'默认情况下只会在'RuntimeException'上回滚而不在'Exception's上。 –

+0

是的,我真的不想测试我的数据库,这个测试只是一种测试我认为交易是如何完成的方式。你能解释一下在测试中@Transactional有什么区别吗? – PhoneixS

回答

0

Spring事务回滚仅用于检查异常,因为异常是部分检查的类,它不回滚事务。 您可以使用@Transactional(rollbackFor =“Throwable.class”)。

+0

我试过了,但结果相同。 – PhoneixS