如何使用 dbUnit 将数据库恢复到初始状态?

Posted

技术标签:

【中文标题】如何使用 dbUnit 将数据库恢复到初始状态?【英文标题】:How to revert the database back to the initial state using dbUnit? 【发布时间】:2011-04-18 08:09:56 【问题描述】:

我是自动化测试和 dbUnit 的新手。所以我很感激你的建议。

我将创建一个测试套件,它将按以下方式运行:

创建内存 H2 数据库 运行 DDL 脚本来创建表 运行 dbUnit 以插入所有测试都将使用的初始数据(我们称之为 STATE0)。 运行测试

直到那里对我来说看起来不错,但我不明白,我如何在测试运行后将数据库恢复到 STATE0 并更改数据?

我可以用 dbUnit 做吗? 还是用别的东西? 我应该在每次测试之前重新创建数据库吗?

在测试中简单的不提交事务不适合我,因为测试最终会运行多个事务,可能不止一个数据库连接。

【问题讨论】:

【参考方案1】:

如果您正确编写@BeforeClass@Before@After 方法,DBUnit 可以自动完成四个工作。例如。在我们的项目中,使用 Derby,一个这样的测试用例看起来像

public class MyTest 
    protected static IDataSet getDataSet() throws Exception 
        URL url = MyTest.class.getClassLoader().getResource("MyDataSet.xml");
        return new XmlDataSet(new FileInputStream(url.getPath()));
    

    private static JdbcDatabaseTester databaseTester;

    @BeforeClass
    public static void setUpClass() throws Exception 
        // Init test environment, session etc.
        databaseTester = new JdbcDatabaseTester(
                "org.apache.derby.jdbc.ClientDriver",
                "jdbc:derby://localhost:1527/myschema", 
                "username", "password");
        databaseTester.setDataSet(getDataSet());
    

    @AfterClass
    public static void tearDownClass() 
        // Close session etc.
    

    @Before
    public void setUp() throws Exception 
        databaseTester.onSetup();
    

    @After
    public void tearDown() throws Exception 
        databaseTester.onTearDown();
    

    @Test
    public void test() throws Exception  ... 

此代码在每次测试后将 DB 模式(的子集)恢复为 MyDataSet.xml 定义的状态。 (请注意,正如@Pascal 评论的那样,重置可能并不总是完整的 - 如果测试修改了不在数据集中的表,它不会受到@Before / @After 方法的影响。)

【讨论】:

这真的“重置”了数据库吗?我的意思是,如果我的测试在表FOO 中插入了一些数据并且如果MyDataSet.xml 不包括FOOFOO 将不会被“重置”,对吧? @Pascal,你可能是对的。作为人类,如果我正在运行涉及表 FOO 的测试,始终建议仔细检查,该表实际上包含在数据集中。 éter 我同意这一点。只是我内心的挑剔者并没有完全相信最后一句话的措辞:)+1。 @Pascal,在我们的职业中,提前挑剔几乎总是比事后道歉要好:-)所以感谢您的评论,我更新了我的答案以使其(希望)更清晰。 【参考方案2】:

要将数据库初始化为初始数据集,只需在测试用例中实现这些方法即可:

@Override
protected DatabaseOperation getSetUpOperation() throws Exception

    return DatabaseOperation.CLEAN_INSERT; // by default (will do DELETE_ALL + INSERT)


@Override
protected DatabaseOperation getTearDownOperation() throws Exception

    return DatabaseOperation.NONE; // by default

如果您的某些测试在空表中插入行(例如,未在初始数据集中定义),您可能会有外键约束。

只需在您的数据集中添加这个空表,没有任何行:

<mydb_mypopulatedtable id="1" name="toto" alias="funky"/>
<mydb_mypopulatedtable id="2" name="titi" alias="groovy"/>
<mydb_mypopulatedtable id="3" name="tutu" alias="creepy"/>

<mydb_myemptytable />

这里,myemptytable 有一个指向 mypopulatedtable 的外键。如果未定义 myemptytable,DBUnit 将尝试删除 mypopulatedtable,但由于约束而失败。如果已定义,DBUnit 将删除之前的 myemptytable 行。

【讨论】:

一直在寻找这个!

以上是关于如何使用 dbUnit 将数据库恢复到初始状态?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不使用静态 @BeforeClass 的情况下设置/拆卸 dbunit 数据集

DBUnit使用案例

大数据实战——hadoop集群崩溃与故障的初始化恢复

如何平滑地将 CSS 动画恢复到当前状态?

java求余的数然后恢复

C# WinForm如何初始化的时候就自动最小化到右下角的状态栏内。