我正在为我的一个项目编写JUnit测试,测试都是用H2数据库完成的。
设置包括XML文件(包含spring bean和db setup),SQL文件(包含数据/模式)和java文件(只是测试)
每当运行JUnit测试套件时,由于重复数据(因为H2在内存中),一些测试会失败,我想知道是否有办法在某个类之前擦除H2数据?
@Stepwise
由于运行我们的一些测试所需的时间限制,我们已经尝试了它并不适用于我们的情况。
@DirtiesContext(classMode=ClassMode.AFTER_EACH_TEST_CLASS)
以上几乎是每个班级的设置或类似的构建。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("test.xml")
public class ABCTest {
private static final Logger log = Logger.getLogger(ABC.class);
@Autowired
private ABCDao;
....
@After
public void tearDown(){
ABCDao = null;
...
}
@Test
public void test() {
...
}
}
如果测试是单独运行的,那么套件因内存中的数据而失败就不会有问题。 我该如何解决这个问题?
答案 0 :(得分:4)
此代码将有效擦除整个H2数据库(只需在使用@Before
,JUnit规则等任何测试方法之前运行它:
public static void truncateAll(JdbcTemplate jdbcTemplate) throws SQLException {
jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY FALSE");
try {
Iterator var1 = getTableNames(jdbcTemplate).iterator();
while(var1.hasNext()) {
String tableName = (String)var1.next();
jdbcTemplate.execute("TRUNCATE TABLE " + tableName);
}
} finally {
jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY TRUE");
}
}
private static List<String> getTableNames(JdbcTemplate jdbcTemplate) throws SQLException {
return (List)jdbcTemplate.execute(new ConnectionCallback() {
public List<String> doInConnection(Connection conn) throws SQLException, DataAccessException {
DatabaseMetaData metaData = conn.getMetaData();
ResultSet tables = metaData.getTables((String)null, (String)null, "%", new String[]{"TABLE"});
ArrayList tableNames = Lists.newArrayList();
try {
while(tables.next()) {
tableNames.add(tables.getString("TABLE_NAME"));
}
} finally {
tables.close();
}
return tableNames;
}
});
}
答案 1 :(得分:1)
阅读本节:
基本上,每个测试都会回滚它所做的任何更改,因此每个测试都有一个新的数据库状态。
答案 2 :(得分:0)
使用该实用工具类在您的类中隔离tet:
TestIsolator.clearDatabase(jdbcTemplate);
实用程序类:
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import lombok.experimental.UtilityClass;
import org.springframework.jdbc.core.ConnectionCallback;
import org.springframework.jdbc.core.JdbcTemplate;
/**
* Вспомогательные методы для обеспечения изоляции тестов.
*/
@UtilityClass
public class TestIsolator {
/**
* Очистить базу от возможных рудиментов ранее выполненных тестов. Очищает все таблицы базы.
*/
public void clearDatabase(JdbcTemplate jdbcTemplate) {
clearDatabase(jdbcTemplate, getTableNames(jdbcTemplate));
}
/**
* Очистить указанные таблицы от возможных рудиментов ранее выполненных тестов.
*/
public void clearDatabase(JdbcTemplate jdbcTemplate, List<String> tableNames) {
jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY FALSE");
tableNames.forEach(tableName -> {
jdbcTemplate.execute("TRUNCATE TABLE " + tableName + " RESTART IDENTITY");
jdbcTemplate.execute("ALTER SEQUENCE " + tableName + "_ID_SEQ" + " RESTART WITH 1");
});
jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY TRUE");
}
/**
* Получить список таблиц базы.
*/
private List<String> getTableNames(JdbcTemplate jdbcTemplate) {
Object tableNames = jdbcTemplate.execute((ConnectionCallback<Object>) callback -> {
ArrayList<String> names = new ArrayList<>();
try (ResultSet tables = callback.getMetaData().getTables(
null, null, "%", new String[]{"TABLE"})) {
while (tables.next()) {
names.add(tables.getString("TABLE_NAME"));
}
}
return names;
});
return (List<String>) tableNames;
}
}