CLOVER🍀

That was when it all began.

DbUnit 3.0.0を試してみる

これは、なにをしたくて書いたもの?

DbUnitがいつの間にか3.0.0になっていたので、少し見てみようかなということで。

Changes / Release 3.0.0

DbUnit 2.8.0と3.0.0でなにが変わったか?

DbUnitについては、以前こちらのエントリーで扱っています。

DbUnitを試してみる - CLOVER🍀

この時のバージョンは2.7.3で、2022年2月12日のリリースです。

そこから随分間が空き、2.8.0が2024年6月2日に、3.0.0が2025年1月25日にリリースされています。

2.8.0、3.0.0でそれぞれなにが変わったかについて、少し書いておきます。

2.8.0ではデータセットのフォーマットにYAMLが追加されました。

Add support for YAML dataset format.

Changes / Release 2.8.0

こちらのページにも、YamlDataSetというクラスが増えています。

DbUnit – Core Components

YamlDataSet (dbUnit Extension 3.0.1-SNAPSHOT API)

3.0.0はメジャーバージョンアップになりますが、大きな変更点としては依存関係がJUnit 4からJUnit 5になったことと、
TableDecoratorDataSetおよびGeneratedColumnFilterSupportが追加されたことでしょう。

Changes / Release 3.0.0

TableDecoratorDataSetGeneratedColumnFilterSupportについてはこちらに記載があります。

Decorator that allows ITables (and ITableMetaDatas, by extension) to be wrapped. This is intended for use cases like filtering out columns from a table.

DbUnit – Core Components

テーブルからカラムをフィルタリングする時に使うようです。

もうひとつのJUnit 4からJUnit 5への切り替えについては、JUnit 5を前提に作り変えたのかなと思っていたのですが、どうやら
そういうものではないようです。

dbUnit / Feature Requests / #222 Make dbUnit compatible with JUnit 5

Getting Startedなどで紹介されているように、DBTestCaseなどのサブクラスとしてテストクラスを作成する方法があります。

DbUnit – Getting Started

ここでJUnit 5らしい書き方は出てきません。

DBTestCaseクラスの親クラスであるDatabaseTestCaseクラスですが、JUnit 5のExtensionインターフェースを
実装しているので@ExtendWithアノテーションで指定できるようになったのかなと思いきや、そういうわけでは
ありません…。

DatabaseTestCase (dbUnit Extension 3.0.1-SNAPSHOT API)

これらのクラスを@ExtendWithアノテーションに指定すると、テストが実行できなくなります。

つまり、使い方自体は変わらず、あくまで依存関係をJUnit 4からJUnit 5に切り替えただけのようです。

ここに気づくまでに、そこそこ時間がかかりました…。

変更点はこんな感じです。

Gitリポジトリーのタグはこちら。

https://sourceforge.net/p/dbunit/code.git/ci/3.0.0/tree/

今回はどう扱おうというところですが、そこまで大きく変わっていないことがわかったので前に書いたエントリーから
データセットYAMLにして使ってみる感じにしましょう。

DbUnitを試してみる - CLOVER🍀

内容的にはほとんど変わっていないので、ソースコードの説明は差分のみ行います。そもそもなにを確認しているのかは、
前のエントリーを見てみてください。

環境

今回の環境はこちら。

$ java --version
openjdk 21.0.7 2025-04-15
OpenJDK Runtime Environment (build 21.0.7+6-Ubuntu-0ubuntu124.04)
OpenJDK 64-Bit Server VM (build 21.0.7+6-Ubuntu-0ubuntu124.04, mixed mode, sharing)


$ mvn --version
Apache Maven 3.9.10 (5f519b97e944483d878815739f519b2eade0a91d)
Maven home: $HOME/.sdkman/candidates/maven/current
Java version: 21.0.7, vendor: Ubuntu, runtime: /usr/lib/jvm/java-21-openjdk-amd64
Default locale: ja_JP, platform encoding: UTF-8
OS name: "linux", version: "6.8.0-62-generic", arch: "amd64", family: "unix"

データベースにはMySQLを使い、172.17.0.2で動作しているものとします。バージョンはこちら。

 MySQL  localhost:33060+ ssl  practice  SQL > select version();
+-----------+
| version() |
+-----------+
| 8.4.5     |
+-----------+
1 row in set (0.0009 sec)

準備

Maven依存関係など。

    <properties>
        <maven.compiler.release>21</maven.compiler.release>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <version>9.3.0</version>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.seasar.doma</groupId>
            <artifactId>doma-core</artifactId>
            <version>3.9.1</version>
        </dependency>

        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.13.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.dbunit</groupId>
            <artifactId>dbunit</artifactId>
            <version>3.0.0</version>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.platform</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.seasar.doma</groupId>
                            <artifactId>doma-processor</artifactId>
                            <version>3.9.1</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>

DbUnitからJUnit 5に関する依存関係を除外しています。

        <dependency>
            <groupId>org.dbunit</groupId>
            <artifactId>dbunit</artifactId>
            <version>3.0.0</version>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.platform</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

これについてなのですが、mvn dependency:treeDbUnitの依存関係を見ると以下のようになっています。

[INFO] \- org.dbunit:dbunit:jar:3.0.0:test
[INFO]    +- org.slf4j:slf4j-api:jar:1.7.25:test
[INFO]    +- org.junit.platform:junit-platform-suite-engine:jar:1.10.1:test
[INFO]    |  +- org.junit.platform:junit-platform-engine:jar:1.10.1:test
[INFO]    |  |  +- org.opentest4j:opentest4j:jar:1.3.0:test
[INFO]    |  |  \- org.junit.platform:junit-platform-commons:jar:1.10.1:test
[INFO]    |  +- org.junit.platform:junit-platform-suite-api:jar:1.10.1:test
[INFO]    |  +- org.apiguardian:apiguardian-api:jar:1.1.2:test
[INFO]    |  \- org.junit.platform:junit-platform-suite-commons:jar:1.10.1:test
[INFO]    |     \- org.junit.platform:junit-platform-launcher:jar:1.10.1:test
[INFO]    \- org.yaml:snakeyaml:jar:2.2:test

ここで違うバージョンのJUnit Platformに依存するJUnit Jupiterを加えると、以下のようにテストが見つからずに失敗して
しまいます。

[ERROR] TestEngine with ID 'junit-jupiter' failed to discover tests
[ERROR] org.apache.maven.surefire.booter.SurefireBooterForkException: There was an error in the forked process
[ERROR] TestEngine with ID 'junit-jupiter' failed to discover tests
[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter.fork(ForkStarter.java:628)
[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:285)
[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:250)
[ERROR]         at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeProvider(AbstractSurefireMojo.java:1337)
[ERROR]         at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeAfterPreconditionsChecked(AbstractSurefireMojo.java:1135)
[ERROR]         at org.apache.maven.plugin.surefire.AbstractSurefireMojo.execute(AbstractSurefireMojo.java:969)
[ERROR]         at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:126)

というわけで、除外することになりました。

データベースアクセスにはDomaを使うので、必要なクラスを作成。

src/main/java/org/littlewings/dbunit/Book.java

package org.littlewings.dbunit;

import java.time.LocalDate;
import org.seasar.doma.Entity;
import org.seasar.doma.Id;

@Entity
public record Book(
        @Id
        String isbn,
        String title,
        Integer price,
        LocalDate publishDate,
        String category
) {
}

src/main/java/org/littlewings/dbunit/BookDao.java

package org.littlewings.dbunit;

import org.seasar.doma.Dao;
import org.seasar.doma.Insert;
import org.seasar.doma.Script;
import org.seasar.doma.Select;
import org.seasar.doma.Sql;
import org.seasar.doma.jdbc.Result;

@Dao
public interface BookDao {
    @Sql("""
            drop table if exists book;
            create table book(
              isbn varchar(14),
              title varchar(100),
              price int,
              publish_date date,
              category varchar(20),
              primary key(isbn)
            )
            """)
    @Script
    void createTableIfExistsRecreate();

    @Sql("truncate table book")
    @Script
    void truncate();

    @Insert
    Result<Book> insert(Book book);

    @Sql("select /*%expand*/* from book where isbn = /* isbn */'dummy'")
    @Select
    Book selectByIsbn(String isbn);
}

src/main/java/org/littlewings/dbunit/DomaConfig.java

package org.littlewings.dbunit;

import javax.sql.DataSource;

import org.seasar.doma.jdbc.Config;
import org.seasar.doma.jdbc.Naming;
import org.seasar.doma.jdbc.dialect.Dialect;
import org.seasar.doma.jdbc.dialect.MysqlDialect;
import org.seasar.doma.jdbc.tx.LocalTransactionDataSource;
import org.seasar.doma.jdbc.tx.LocalTransactionManager;
import org.seasar.doma.jdbc.tx.TransactionManager;

public class DomaConfig implements Config {
    private static final DomaConfig CONFIG = new DomaConfig();

    Dialect dialect;

    LocalTransactionDataSource dataSource;

    TransactionManager transactionManager;

    public static DomaConfig singleton() {
        return CONFIG;
    }

    private DomaConfig() {
        dialect = new MysqlDialect(MysqlDialect.MySqlVersion.V8);
        dataSource = new LocalTransactionDataSource(
                "jdbc:mysql://172.17.0.2:3306/practice?characterEncoding=utf-8&characterSetResults=utf-8&connectionCollation=utf8mb4_0900_bin",
                "kazuhira",
                "password"
        );
        transactionManager = new LocalTransactionManager(dataSource.getLocalTransaction(getJdbcLogger()));
    }

    @Override
    public DataSource getDataSource() {
        return dataSource;
    }

    @Override
    public Dialect getDialect() {
        return dialect;
    }

    @Override
    public TransactionManager getTransactionManager() {
        return transactionManager;
    }

    @Override
    public Naming getNaming() {
        return Naming.SNAKE_LOWER_CASE;
    }
}

こちらも以前のエントリーの内容に近いのですが、エンティティークラスはRecordsにしています。

あとはMySQL 8以降専用にしました。

設定 / 設定可能な項目 / SQL ダイアレクト

DbUnitを使う

あとはDbUnitを使っていってみます。

もっとも、コード自体は以前に書いたエントリーから少し変えたものですが。

DbUnitを試してみる - CLOVER🍀

テストコードの雛形は以下とします。

src/test/java/org/littlewings/dbunit/DbUnitGettingStartedTest.java

package org.littlewings.dbunit;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.time.LocalDate;
import java.util.List;
import org.dbunit.Assertion;
import org.dbunit.DatabaseUnitException;
import org.dbunit.database.DatabaseConfig;
import org.dbunit.database.DatabaseConnection;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.ITable;
import org.dbunit.dataset.SortedTable;
import org.dbunit.dataset.yaml.YamlDataSet;
import org.dbunit.ext.mysql.MySqlConnection;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

class DbUnitGettingStartedTest {
    @BeforeAll
    static void setUpAll() {
        BookDao bookDao = new BookDaoImpl(DomaConfig.singleton());
        DomaConfig
                .singleton()
                .getTransactionManager()
                .required(bookDao::createTableIfExistsRecreate);
    }

    @BeforeEach
    void setUp() {
        BookDao bookDao = new BookDaoImpl(DomaConfig.singleton());
        DomaConfig
                .singleton()
                .getTransactionManager()
                .required(bookDao::truncate);
    }

    // ここに、テストを書く
}

まずはデータベース接続。

    @Test
    void createDbUnitConnection() throws DatabaseUnitException, SQLException {
        DatabaseConnection databaseConnection = null;
        try (Connection conn = DriverManager
                .getConnection(
                        "jdbc:mysql://172.17.0.2:3306/practice?characterEncoding=utf-8&characterSetResults=utf-8&connectionCollation=utf8mb4_0900_bin",
                        "kazuhira",
                        "password");) {
            databaseConnection = new MySqlConnection(conn, null);
            databaseConnection.getConfig().setProperty(DatabaseConfig.FEATURE_CASE_SENSITIVE_TABLE_NAMES, true);
        } finally {
            if (databaseConnection != null) {
                databaseConnection.close();
            }
        }
    }
}

前のコードからは、以下の1行が増えています。

            databaseConnection.getConfig().setProperty(DatabaseConfig.FEATURE_CASE_SENSITIVE_TABLE_NAMES, true);

これは、大文字・小文字を区別しないようにするとデータベースから取得したテーブルの名前を大文字に変換してしまうようなので、
今回はそれを抑制するために入れました。

小文字で書いているんですよ…。

アサーション

    @Test
    void firstAssertion() throws DatabaseUnitException, SQLException {
        DatabaseConnection databaseConnection = null;
        try (Connection conn = DriverManager
                .getConnection(
                        "jdbc:mysql://172.17.0.2:3306/practice?characterEncoding=utf-8&characterSetResults=utf-8&connectionCollation=utf8mb4_0900_bin",
                        "kazuhira",
                        "password");) {
            databaseConnection = new MySqlConnection(conn, null);
            databaseConnection.getConfig().setProperty(DatabaseConfig.FEATURE_CASE_SENSITIVE_TABLE_NAMES, true);

            DomaConfig
                    .singleton()
                    .getTransactionManager()
                    .required(() -> {
                        BookDao bookDao = new BookDaoImpl(DomaConfig.singleton());

                        List<Book> books = List.of(
                                new Book("978-4295008477", "新世代Javaプログラミングガイド[Java SE 10/11/12/13と言語拡張プロジェクト]", 2860, LocalDate.of(2020, 3, 13), "java"),
                                new Book("978-4621303252", "Effective Java 第3版", 4400, LocalDate.of(2018, 10, 30), "java"),
                                new Book("978-4774189093", "Java本格入門 〜モダンスタイルによる基礎からオブジェクト指向・実用ライブラリまで", 3278, LocalDate.of(2017, 4, 18), "java"),
                                new Book("978-4798161488", "MySQL徹底入門 第4版 MySQL 8.0対応", 4180, LocalDate.of(2020, 7, 6), "mysql"),
                                new Book("978-4798147406", "詳解MySQL 5.7 止まらぬ進化に乗り遅れないためのテクニカルガイド", 3960, LocalDate.of(2016, 8, 26), "mysql")
                        );

                        books.forEach(bookDao::insert);
                    });

            IDataSet actualDataSet = databaseConnection.createDataSet();
            ITable actualTable = actualDataSet.getTable("book");

            IDataSet expectedDataSet =
                    new YamlDataSet(getClass().getClassLoader().getResourceAsStream("DbUnitGettingStartedTest.firstAssertion.yaml"));
            ITable expectedTable = expectedDataSet.getTable("book");

            // assert dataset
            Assertion.assertEquals(expectedDataSet, actualDataSet);
            // assert table
            Assertion.assertEquals(expectedTable, actualTable);
        } finally {
            if (databaseConnection != null) {
                databaseConnection.close();
            }
        }
    }

データセットYAMLを使う場合は、YamlDataSetクラスを使います。ビルダークラスはないようです。

            IDataSet expectedDataSet =
                    new YamlDataSet(getClass().getClassLoader().getResourceAsStream("DbUnitGettingStartedTest.firstAssertion.yaml"));

確認用に使っているデータセットはこちらです。

src/test/resources/DbUnitGettingStartedTest.firstAssertion.yaml

book:
  - isbn: "978-4295008477"
    title: "新世代Javaプログラミングガイド[Java SE 10/11/12/13と言語拡張プロジェクト]"
    price: 2860
    publish_date: "2020-03-13"
    category: "java"
  - isbn: "978-4621303252"
    title: "Effective Java 第3版"
    price: 4400
    publish_date: "2018-10-30"
    category: "java"
  - isbn: "978-4774189093"
    title: "Java本格入門 〜モダンスタイルによる基礎からオブジェクト指向・実用ライブラリまで"
    price: 3278
    publish_date: "2017-04-18"
    category: "java"
  - isbn: "978-4798147406"
    title: "詳解MySQL 5.7 止まらぬ進化に乗り遅れないためのテクニカルガイド"
    price: 3960
    publish_date: "2016-08-26"
    category: "mysql"
  - isbn: "978-4798161488"
    title: "MySQL徹底入門 第4版 MySQL 8.0対応"
    price: 4180
    publish_date: "2020-07-06"
    category: "mysql"

SQLを使って、アサーション対象となるデータを絞り込む例。

    @Test
    void createDataSetFromQuery() throws DatabaseUnitException, SQLException {
        DatabaseConnection databaseConnection = null;
        try (Connection conn = DriverManager
                .getConnection(
                        "jdbc:mysql://172.17.0.2:3306/practice?characterEncoding=utf-8&characterSetResults=utf-8&connectionCollation=utf8mb4_0900_bin",
                        "kazuhira",
                        "password");) {
            databaseConnection = new MySqlConnection(conn, null);
            databaseConnection.getConfig().setProperty(DatabaseConfig.FEATURE_CASE_SENSITIVE_TABLE_NAMES, true);

            DomaConfig
                    .singleton()
                    .getTransactionManager()
                    .required(() -> {
                        BookDao bookDao = new BookDaoImpl(DomaConfig.singleton());

                        List<Book> books = List.of(
                                new Book("978-4295008477", "新世代Javaプログラミングガイド[Java SE 10/11/12/13と言語拡張プロジェクト]", 2860, LocalDate.of(2020, 3, 13), "java"),
                                new Book("978-4621303252", "Effective Java 第3版", 4400, LocalDate.of(2018, 10, 30), "java"),
                                new Book("978-4774189093", "Java本格入門 〜モダンスタイルによる基礎からオブジェクト指向・実用ライブラリまで", 3278, LocalDate.of(2017, 4, 18), "java"),
                                new Book("978-4798161488", "MySQL徹底入門 第4版 MySQL 8.0対応", 4180, LocalDate.of(2020, 7, 6), "mysql"),
                                new Book("978-4798147406", "詳解MySQL 5.7 止まらぬ進化に乗り遅れないためのテクニカルガイド", 3960, LocalDate.of(2016, 8, 26), "mysql")
                        );

                        books.forEach(bookDao::insert);
                    });

            ITable actualTable =
                    databaseConnection
                            .createQueryTable("query_result", "select * from book where category = 'mysql' order by isbn asc");

            IDataSet expectedDataSet =
                    new YamlDataSet(getClass().getClassLoader().getResourceAsStream("DbUnitGettingStartedTest.createDataSetFromQuery.yaml"));
            ITable expectedTable = expectedDataSet.getTable("book");

            Assertion.assertEquals(expectedTable, actualTable);
        } finally {
            if (databaseConnection != null) {
                databaseConnection.close();
            }
        }
    }

確認対象のデータセット

src/test/resources/DbUnitGettingStartedTest.createDataSetFromQuery.yaml

book:
  - isbn: "978-4798147406"
    title: "詳解MySQL 5.7 止まらぬ進化に乗り遅れないためのテクニカルガイド"
    price: 3960
    publish_date: "2016-08-26"
    category: "mysql"
  - isbn: "978-4798161488"
    title: "MySQL徹底入門 第4版 MySQL 8.0対応"
    price: 4180
    publish_date: "2020-07-06"
    category: "mysql"

データセットはデフォルトでプライマリーキーでソートされますが、他のソートキーを使う例。

    @Test
    void sortTable() throws DatabaseUnitException, SQLException {
        DatabaseConnection databaseConnection = null;
        try (Connection conn = DriverManager
                .getConnection(
                        "jdbc:mysql://172.17.0.2:3306/practice?characterEncoding=utf-8&characterSetResults=utf-8&connectionCollation=utf8mb4_0900_bin",
                        "kazuhira",
                        "password");) {
            databaseConnection = new MySqlConnection(conn, null);
            databaseConnection.getConfig().setProperty(DatabaseConfig.FEATURE_CASE_SENSITIVE_TABLE_NAMES, true);

            DomaConfig
                    .singleton()
                    .getTransactionManager()
                    .required(() -> {
                        BookDao bookDao = new BookDaoImpl(DomaConfig.singleton());

                        List<Book> books = List.of(
                                new Book("978-4295008477", "新世代Javaプログラミングガイド[Java SE 10/11/12/13と言語拡張プロジェクト]", 2860, LocalDate.of(2020, 3, 13), "java"),
                                new Book("978-4621303252", "Effective Java 第3版", 4400, LocalDate.of(2018, 10, 30), "java"),
                                new Book("978-4774189093", "Java本格入門 〜モダンスタイルによる基礎からオブジェクト指向・実用ライブラリまで", 3278, LocalDate.of(2017, 4, 18), "java"),
                                new Book("978-4798161488", "MySQL徹底入門 第4版 MySQL 8.0対応", 4180, LocalDate.of(2020, 7, 6), "mysql"),
                                new Book("978-4798147406", "詳解MySQL 5.7 止まらぬ進化に乗り遅れないためのテクニカルガイド", 3960, LocalDate.of(2016, 8, 26), "mysql")
                        );

                        books.forEach(bookDao::insert);
                    });

            IDataSet actualDataSet = databaseConnection.createDataSet();
            SortedTable actualTable = new SortedTable(actualDataSet.getTable("book"), new String[]{"price"});
            actualTable.setUseComparable(true);

            IDataSet expectedDataSet =
                    new YamlDataSet(getClass().getClassLoader().getResourceAsStream("DbUnitGettingStartedTest.sortTable.yaml"));
            ITable expectedTable = expectedDataSet.getTable("book");
            // SortedTable expectedTable = new SortedTable(expectedDataSet.getTable("book"), new String[]{"price"});
            // expectedTable.setUseComparable(true);

            Assertion.assertEquals(expectedTable, actualTable);
        } finally {
            if (databaseConnection != null) {
                databaseConnection.close();
            }
        }
    }
}

確認対象のデータセット

src/test/resources/DbUnitGettingStartedTest.sortTable.yaml

book:
  - isbn: "978-4295008477"
    title: "新世代Javaプログラミングガイド[Java SE 10/11/12/13と言語拡張プロジェクト]"
    price: 2860
    publish_date: "2020-03-13"
    category: "java"
  - isbn: "978-4774189093"
    title: "Java本格入門 〜モダンスタイルによる基礎からオブジェクト指向・実用ライブラリまで"
    price: 3278
    publish_date: "2017-04-18"
    category: "java"
  - isbn: "978-4798147406"
    title: "詳解MySQL 5.7 止まらぬ進化に乗り遅れないためのテクニカルガイド"
    price: 3960
    publish_date: "2016-08-26"
    category: "mysql"
  - isbn: "978-4798161488"
    title: "MySQL徹底入門 第4版 MySQL 8.0対応"
    price: 4180
    publish_date: "2020-07-06"
    category: "mysql"
  - isbn: "978-4621303252"
    title: "Effective Java 第3版"
    price: 4400
    publish_date: "2018-10-30"
    category: "java"

今回は確認対象のデータセットはソート済みとしていますが、DbUnitにソートさせる場合はコメントアウトしている箇所と
入れ替えます。

            ITable expectedTable = expectedDataSet.getTable("book");
            // SortedTable expectedTable = new SortedTable(expectedDataSet.getTable("book"), new String[]{"price"});
            // expectedTable.setUseComparable(true);

ソート順も合っていないと、アサーションに失敗します。

DatabaseOperationを使った場合。

src/test/java/org/littlewings/dbunit/DbUnitOperationTest.java

package org.littlewings.dbunit;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.time.LocalDate;
import java.util.List;
import org.dbunit.Assertion;
import org.dbunit.DatabaseUnitException;
import org.dbunit.database.DatabaseConfig;
import org.dbunit.database.DatabaseConnection;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.ITable;
import org.dbunit.dataset.yaml.YamlDataSet;
import org.dbunit.ext.mysql.MySqlConnection;
import org.dbunit.operation.DatabaseOperation;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

class DbUnitOperationTest {
    @BeforeAll
    public static void setUpAll() {
        BookDao bookDao = new BookDaoImpl(DomaConfig.singleton());
        DomaConfig
                .singleton()
                .getTransactionManager()
                .required(bookDao::createTableIfExistsRecreate);
    }

    @Test
    void test() throws SQLException, DatabaseUnitException {
        DatabaseConnection databaseConnection = null;
        try (Connection conn = DriverManager
                .getConnection(
                        "jdbc:mysql://172.17.0.2:3306/practice?characterEncoding=utf-8&characterSetResults=utf-8&connectionCollation=utf8mb4_0900_bin",
                        "kazuhira",
                        "password");) {
            databaseConnection = new MySqlConnection(conn, null);
            databaseConnection.getConfig().setProperty(DatabaseConfig.FEATURE_CASE_SENSITIVE_TABLE_NAMES, true);

            // INSERT Operation
            IDataSet insertedDataSet =
                    new YamlDataSet(getClass().getClassLoader().getResourceAsStream("DbUnitOperationTest.test.yaml"));

            DatabaseOperation.INSERT.execute(databaseConnection, insertedDataSet);
            // JUnit 5 Assersions
            Assertions.assertEquals(2, databaseConnection.getRowCount("book"));

            DomaConfig
                    .singleton()
                    .getTransactionManager()
                    .required(() -> {
                        BookDao bookDao = new BookDaoImpl(DomaConfig.singleton());

                        List<Book> books = List.of(
                                new Book("978-4295008477", "新世代Javaプログラミングガイド[Java SE 10/11/12/13と言語拡張プロジェクト]", 2860, LocalDate.of(2020, 3, 13), "java"),
                                new Book("978-4621303252", "Effective Java 第3版", 4400, LocalDate.of(2018, 10, 30), "java"),
                                new Book("978-4774189093", "Java本格入門 〜モダンスタイルによる基礎からオブジェクト指向・実用ライブラリまで", 3278, LocalDate.of(2017, 4, 18), "java"),
                                new Book("978-4798161488", "MySQL徹底入門 第4版 MySQL 8.0対応", 4180, LocalDate.of(2020, 7, 6), "mysql"),
                                new Book("978-4798147406", "詳解MySQL 5.7 止まらぬ進化に乗り遅れないためのテクニカルガイド", 3960, LocalDate.of(2016, 8, 26), "mysql")
                        );

                        books.forEach(bookDao::insert);
                    });

            Assertions.assertEquals(7, databaseConnection.getRowCount("book"));

            // REFRESH(update or insert) Operation
            IDataSet refreshedDataSet =
                    new YamlDataSet(getClass().getClassLoader().getResourceAsStream("DbUnitOperationTest.test.yaml"));

            // no effect
            DatabaseOperation.REFRESH.execute(databaseConnection, refreshedDataSet);
            // JUnit 5 Assersions
            Assertions.assertEquals(7, databaseConnection.getRowCount("book"));
            ITable categories = databaseConnection.createQueryTable("result", "select category from book group by category order by category");
            Assertions.assertEquals("java", categories.getValue(0, "category"));
            Assertions.assertEquals("linux", categories.getValue(1, "category"));
            Assertions.assertEquals("mysql", categories.getValue(2, "category"));

            // CLEAN_INSERT(delete all + insert) Operation
            DatabaseOperation.CLEAN_INSERT.execute(databaseConnection, insertedDataSet);

            IDataSet actualDataSet = databaseConnection.createDataSet();

            // JUnit 5 Assersions
            Assertions.assertEquals(2, databaseConnection.getRowCount("book"));
            // DbUnit Assertion
            Assertion.assertEquals(insertedDataSet, actualDataSet);
        } finally {
            if (databaseConnection != null) {
                databaseConnection.close();
            }
        }
    }
}

データ登録および確認対象のデータセット

src/test/resources/DbUnitOperationTest.test.yaml

book:
  - isbn: "978-4797397642"
    title: "本気で学ぶ Linux実践入門 サーバ運用のための業務レベル管理術"
    price: 3278
    publish_date: "2019-05-30"
    category: "linux"
  - isbn: "978-4798155760"
    title: "Ubuntuサーバー徹底入門"
    price: 4180
    publish_date: "2018-06-13"
    category: "linux"

こんなところでしょうか。

おわりに

DbUnit 3.0.0がリリースされていたので、確認を兼ねて軽く試してみました。

YAMLが使えるようになったことと、JUnit 4への依存関係のみがなくなったことを除いて、あまり変わってはいない感じですね。
実際に使う時には今までどおり使えるでしょう。

個人的には、この手のデータベースを使ったテスト用ライブラリー(Database RiderやAssertJ-DBなど)の更新が滞っている
ところが気になっています。

やっぱり厳しいんでしょうねぇ…。