【发布时间】:2016-09-07 22:32:13
【问题描述】:
我想知道交易在春季是如何运作的,而且我或多或少地学会了它(或者我认为我已经学会了它)。唯一没有得到的是:为了检查回滚如何发挥它的魔力,我创建了一个测试,该测试调用带有 @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 注释的类。 ArchivosEnDiscoRepo 是 CrudRepository。我的 pom 中有 spring-boot-starter-data-jpa 和 hsqldb,但没有配置 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());
}
}
【问题讨论】:
-
这是一个内部方法调用,所以你的
@Transactional几乎没用。除此之外,即使不是这样,它也不会起作用,因为@Transactional在测试用例中不是这样工作的!此外,您没有测试任何与数据库相关的内容,您只是在测试一级缓存。最后@Transactional将默认只回滚RuntimeExceptions 而不是Exceptions。 -
是的,我并没有真正尝试测试我的数据库,这个测试只是一种测试我认为事务是如何完成的方法。你能解释一下@Transactional 在测试中有什么区别吗?
标签: spring transactions spring-data