我使用Liquibase作为Java集成测试的一部分。在集成测试阶段,我使用Liquibase在@BeforeClass函数中创建和填充我的表。我的变更集在应用后会被标记。在@After函数中,我运行回滚到特定标记。
然后我可以从数据库和INSERT运行单元测试到SELECT。但是,然后我尝试在每次测试后回滚更改,并发现Liquibase没有回滚我的更改。
我正在对嵌入式Derby数据库使用Liquibase 3.1.1。
我的变更集文件:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">
<include file="create-table-event-type.xml" relativeToChangelogFile="true"/>
<include file="load-table-event-type.xml" relativeToChangelogFile="true"/>
<include file="create-table-event.xml" relativeToChangelogFile="true"/>
<include file="load-table-event.xml" relativeToChangelogFile="true"/>
<changeSet id="tag-integration-test-database" author="Ivan Suftin" context="integration-test">
<tagDatabase tag="integration-tests-tag" />
</changeSet>
</databaseChangeLog>
我的单元测试:
@Category(IntegrationTest.class)
public class EventDAOTest {
private static Connection conn;
private static SqlSessionFactory sqlSessionFactory;
private static Liquibase liquibase;
private EventDAO instance = null;
private static final String rollbackTag = "integration-tests-tag";
private static final Contexts contexts = new Contexts("integration-test");
public EventDAOTest() {
}
@BeforeClass
public static void setUpClass() throws ClassNotFoundException, SQLException, DatabaseException, LiquibaseException, InstantiationException, IllegalAccessException, IOException {
String port = System.getProperty("db.twitter.integration-test.port");
String driver = System.getProperty("db.twitter.integration-test.driver");
String dbType = System.getProperty("db.twitter.integration-test.dbtype");
String schema = System.getProperty("db.twitter.integration-test.schema");
if (StringUtils.isBlank(port)) {
throw new NullPointerException("System property \"db.twitter.integration-test.port\" not found");
}
if (StringUtils.isBlank(driver)) {
throw new NullPointerException("System property \"db.twitter.integration-test.driver\" not found");
}
if (StringUtils.isBlank(dbType)) {
throw new NullPointerException("System property \"db.twitter.integration-test.dbType\" not found");
}
if (StringUtils.isBlank(schema)) {
throw new NullPointerException("System property \"db.twitter.integration-test.schema\" not found");
}
Class.forName(driver).newInstance();
conn = DriverManager.getConnection("jdbc:" + dbType + "://localhost:" + port + "/" + schema + ";create=true", "test", "test");
Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(conn));
liquibase = new Liquibase("src/main/resources/liquibase/changelogs/create-table-parent-changeLog.xml", new FileSystemResourceAccessor(), database);
liquibase.update(contexts);
try (InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml")) {
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream, "integration-test");
}
}
@AfterClass
public static void tearDownClass() throws SQLException {
conn.close();
}
@Before
public void beforeTest() {
instance = new EventDAO(sqlSessionFactory);
}
@After
public void afterTest() throws DatabaseException, LiquibaseException {
liquibase.rollback(rollbackTag, contexts);
}
[...]
测试的其余部分只是我使用MyBatis进行SELECT和INSERT。
这是日志的样子(只是粘贴重要部分)
INFO 3/8/14 7:23 PM:liquibase: Successfully acquired change log lock
INFO 3/8/14 7:23 PM:liquibase: Creating database history table with name: TEST.DATABASECHANGELOG
INFO 3/8/14 7:23 PM:liquibase: Reading from TEST.DATABASECHANGELOG
[...运行变更集...]
INFO 3/8/14 7:23 PM:liquibase: src/main/resources/liquibase/changelogs/create-table-parent-changeLog.xml: tag-integration-test-database::Ivan Suftin: Reading from TEST.DATABASECHANGELOG
INFO 3/8/14 7:23 PM:liquibase: src/main/resources/liquibase/changelogs/create-table-parent-changeLog.xml: tag-integration-test-database::Ivan Suftin: Tag 'integration-tests-tag' applied to database
INFO 3/8/14 7:23 PM:liquibase: src/main/resources/liquibase/changelogs/create-table-parent-changeLog.xml: tag-integration-test-database::Ivan Suftin: ChangeSet src/main/resources/liquibase/changelogs/create-table-parent-changeLog.xml::tag-integration-test-database::Ivan Suftin ran successfully in 11ms
INFO 3/8/14 7:23 PM:liquibase: src/main/resources/liquibase/changelogs/create-table-parent-changeLog.xml: tag-integration-test-database::Ivan Suftin: Reading from TEST.DATABASECHANGELOG
INFO 3/8/14 7:23 PM:liquibase: Successfully released change log lock
在每次测试之间,我尝试运行回滚,所以我得到一个新加载的数据库,并在此处显示日志:
INFO 3/8/14 7:23 PM:liquibase: Successfully acquired change log lock
INFO 3/8/14 7:23 PM:liquibase: Reading from TEST.DATABASECHANGELOG
INFO 3/8/14 7:23 PM:liquibase: Reading from TEST.DATABASECHANGELOG
INFO 3/8/14 7:23 PM:liquibase: Successfully released change log lock
-- *********************************************************************
-- Rollback to 'integration-tests-tag' Script
-- *********************************************************************
-- Change Log: src/main/resources/liquibase/changelogs/create-table-parent-changeLog.xml
-- Ran at: 3/8/14 7:23 PM
-- Against: test@jdbc:derby://localhost:59527/twitter;create=true
-- Liquibase version: 3.1.1
-- *********************************************************************
-- Lock Database
-- Rolling Back ChangeSet: src/main/resources/liquibase/changelogs/create-table-parent-changeLog.xml::tag-integration-test-database::Ivan Suftin
DELETE FROM TEST.DATABASECHANGELOG WHERE ID='tag-integration-test-database' AND AUTHOR='Ivan Suftin' AND FILENAME='src/main/resources/liquibase/changelogs/create-table-parent-changeLog.xml';
-- Release Database Lock
我测试的表最初有两行。我有两个插入测试。他们一个接一个地跑。在第一个测试中,我运行一行INSERT,然后立即运行SELECT来计算行数。结果显示3行,这是正确的。
下一个测试还运行一行INSERT,然后我再次运行SELECT来测试行数,它应该是3行,但现在我得到4行。这告诉我@After函数中的回滚实际上什么都不做。
我在这里做错了吗?
我还尝试使用Java API在运行更改日志后立即创建标记:
liquibase.tag(rollbackTag);
...但我得到了相同的结果。什么都没有回滚。
答案 0 :(得分:5)
Liquibase不会自动为insert语句生成回滚命令,因此除非你手动将它们放入Liquibase中,否则不会做任何事情。有关该文档,请参阅http://www.liquibase.org/documentation/rollback.html。
许多重构,例如“创建表”,“重命名列”和“添加” 列“可以自动创建回滚语句。如果你改变了 log只包含适合此类别的语句 回滚命令将自动生成。
其他重构,例如“drop table”和“insert data”都没有 可自动生成的相应回滚命令。 在这些情况下,以及您要覆盖默认值的情况 生成的回滚命令,可以通过指定回滚命令 changeSet标记中的标记。如果你不想做任何事情 撤消回滚模式的更改,使用空标记。