[英]How to clean database tables after each integration test when using Spring Boot and Liquibase?
I have a side project were I'm using Spring Boot, Liquibase and Postgres.我有一个附带项目,我正在使用 Spring Boot、Liquibase 和 Postgres。
I have the following sequence of tests:我有以下测试序列:
test1();
test2();
test3();
test4();
In those four tests I'm creating the same entity.在这四个测试中,我正在创建相同的实体。 As I'm not removing the records from the table after each test case, I'm getting the following exception:
org.springframework.dao.DataIntegrityViolationException
由于我没有在每个测试用例之后从表中删除记录,因此出现以下异常:
org.springframework.dao.DataIntegrityViolationException
I want to solve this problem with the following constraints:我想通过以下约束来解决这个问题:
@repository
to clean the database.@repository
来清理数据库。 In short: How can I remove the records from one or more tables after each test case without 1) using the @repository
of each entity and 2) killing and starting the database container on each test case?简而言之:如何在每个测试用例之后从一个或多个表中删除记录,而无需 1)使用每个实体的
@repository
和 2)在每个测试用例上杀死并启动数据库容器?
The simplest way I found to do this was the following:我发现执行此操作的最简单方法如下:
@Autowired
private JdbcTemplate jdbcTemplate;
JdbcTestUtils.deleteFromTables(jdbcTemplate, "table1", "table2", "table3");
@After
or @AfterEach
in your test class:@After
或@AfterEach
注释的方法中调用此行:@AfterEach
void tearDown() throws DatabaseException {
JdbcTestUtils.deleteFromTables(jdbcTemplate, "table1", "table2", "table3");
}
I found this approach in this blog post: Easy Integration Testing With Testcontainers我在这篇博文中找到了这种方法: 使用 Testcontainers 进行轻松集成测试
Annotate your test class with @DataJpaTest
.使用 @DataJpaTest 注释您的测试
@DataJpaTest
。 From the documentation:从文档中:
By default, tests annotated with @DataJpaTest are transactional and roll back at the end of each test.
默认情况下,使用 @DataJpaTest 注释的测试是事务性的,并在每个测试结束时回滚。 They also use an embedded in-memory database (replacing any explicit or usually auto-configured DataSource).
他们还使用嵌入式内存数据库(替换任何显式或通常自动配置的数据源)。
For example using Junit4:例如使用 Junit4:
@RunWith(SpringRunner.class)
@DataJpaTest
public class MyTest {
//...
}
Using Junit5:使用 Junit5:
@DataJpaTest
public class MyTest {
//...
}
You could use @Transactional on your test methods.您可以在测试方法上使用 @Transactional。 That way, each test method will run inside its own transaction bracket and will be rolled back before the next test method will run.
这样,每个测试方法都将在其自己的事务括号内运行,并在下一个测试方法运行之前回滚。
Of course, this only works if you are not doing anything weird with manual transaction management, and it is reliant on some Spring Boot autoconfiguration magic, so it may not be possible in every use case, but it is generally a highly performant and very simple approach to isolating test cases.当然,这仅在您没有对手动事务管理做任何奇怪的事情时才有效,并且它依赖于一些 Spring 引导自动配置魔术,因此可能无法在每个用例中使用,但它通常是高性能且非常简单的隔离测试用例的方法。
i think this is the most effecient way for postgreSQL.我认为这是 postgreSQL 最有效的方法。 You can make same thing for other db.
你可以为其他数据库做同样的事情。 Just find how to restart tables sequence and execute it
只需找到如何重新启动表序列并执行它
@Autowired
private JdbcTemplate jdbcTemplate;
@AfterEach
public void execute() {
jdbcTemplate.execute("TRUNCATE TABLE users" );
jdbcTemplate.execute("ALTER SEQUENCE users_id_seq RESTART");
}
My personal preference would be:我个人的偏好是:
private static final String CLEAN_TABLES_SQL[] = {
"delete from table1",
"delete from table2",
"delete from table3"
};
@After
public void tearDown() {
for (String query : CLEAN_TABLES_SQL)
{
getJdbcTemplate().execute(query);
}
}
To be able to adopt this approach, you would need to extend the class with DaoSupport, and set the DataSource in the constructor.为了能够采用这种方法,您需要使用 DaoSupport 扩展 class,并在构造函数中设置 DataSource。
public class Test extends NamedParameterJdbcDaoSupport
public Test(DataSource dataSource)
{
setDataSource(dataSource);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.