CLOVER🍀

That was when it all began.

Database RiderをSpring Framework(Spring Boot)と合わせて使う時に、Rider JUnit 5とRider Springのどちらを使うか?

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

以前、こんなエントリーを書きました。

Database RiderをSpring Framework(Spring Boot)と合わせて使う - CLOVER🍀

Spring Framework 5以降であれば、rider-junit5を使うのがよいのだろうと思ったのですが、ちょっと気になる差異があったので確認して
みました。

Database RiderとSpring Framework

Database RiderとSpring Frameworkを組み合わせる場合、選択肢として次の2つのモジュールがあります。

Rider Springモジュールの方に注意書きが書かれているのですが、Rider SpringモジュールはJUnit 4とSpringRunner向けに設計されたもの
なので、JUnit 5を組み合わせる場合はRider JUnit 5モジュールを使うことが勧められています。

This module is designed to work with JUnit4 and SpringRunner, for JUnit5 please use @DBRider annotation from JUnit5 module, see an example here.

一方で、実装方法なのですが。

Rider JUnit 5モジュールは、JUnit 5のテストライフサイクルコールバックの仕組みで実現されています。

JUnit 5 User Guide / Extension Model / Test Lifecycle Callbacks

https://github.com/database-rider/database-rider/blob/1.36.0/rider-junit5/src/main/java/com/github/database/rider/junit5/api/DBRider.java

https://github.com/database-rider/database-rider/blob/1.36.0/rider-junit5/src/main/java/com/github/database/rider/junit5/DBUnitExtension.java

Rider Springモジュールは、Spring TestのTestExecutionListenerの仕組みで実現されています。

Testing / Spring TestContext Framework / TestExecutionListener Configuration

https://github.com/database-rider/database-rider/blob/master/rider-spring/src/main/java/com/github/database/rider/spring/api/DBRider.java

https://github.com/database-rider/database-rider/blob/master/rider-spring/src/main/java/com/github/database/rider/spring/DBRiderTestExecutionListener.java

サンプルに書かれているように、こういった使い方をRider JUnit 5モジュールで実現できます。

    @Test
    @ExpectedDataSet("expectedUsers.yml")
    public void shouldDeleteUser() {
        assertThat(userRepository).isNotNull();
        assertThat(userRepository.count()).isEqualTo(3);
        userRepository.findById(2L).ifPresent(userRepository::delete);
        //assertThat(userRepository.count()).isEqualTo(2); //assertion is made by @ExpectedDataset
    }


    @Test
    @DataSet(cleanBefore = true)//as we didn't declared a dataset DBUnit wont clear the table
    @ExpectedDataSet("user.yml")
    public void shouldInsertUser() {
        assertThat(userRepository).isNotNull();
        assertThat(userRepository.count()).isEqualTo(0);
        userRepository.save(new User("newUser@gmail.com", "new user"));
        //assertThat(userRepository.count()).isEqualTo(1); //assertion is made by @ExpectedDataset
    }

https://github.com/database-rider/database-rider/blob/1.36.0/rider-examples/spring-boot-dbunit-sample/src/test/java/com/github/database/rider/springboot/SpringBootDBUnitTest.java

これなら問題ないのですが、Spring Frameworkの@Transactionalを使うと話が変わってきます。テストメソッドに@Transactionalを
付与すると、テストメソッドの実行終了時にロールバックしてくれます。

Testing / Spring TestContext Framework / Transaction Management

今回は、この2つのモジュールで@Transactionalと組み合わせるとどうなるかを見ていこうと思います。

環境

今回の環境は、こちら。

java --version
openjdk 17.0.6 2023-01-17
OpenJDK Runtime Environment (build 17.0.6+10-Ubuntu-0ubuntu122.04)
OpenJDK 64-Bit Server VM (build 17.0.6+10-Ubuntu-0ubuntu122.04, mixed mode, sharing)


$ mvn --version
Apache Maven 3.9.1 (2e178502fcdbffc201671fb2537d0cb4b4cc58f8)
Maven home: $HOME/.sdkman/candidates/maven/current
Java version: 17.0.6, vendor: Private Build, runtime: /usr/lib/jvm/java-17-openjdk-amd64
Default locale: ja_JP, platform encoding: UTF-8
OS name: "linux", version: "5.15.0-67-generic", arch: "amd64", family: "unix"

データベースには、MySQLを使用します。

 MySQL  localhost:3306 ssl  practice  SQL > select version();
+-----------+
| version() |
+-----------+
| 8.0.32    |
+-----------+
1 row in set (0.0285 sec)

MySQLは172.17.0.2で動作しているものとし、データベースpractice、アカウントはkazuhira/passwordで接続できるものと します。

Spring Bootプロジェクトを作成する

Spring Bootプロジェクトを作成します。依存関係にはjdbcとmysqlを含めておきます。

$ curl -s https://start.spring.io/starter.tgz \
  -d bootVersion=3.0.1 \
  -d javaVersion=17 \
  -d type=maven-project \
  -d name=database-rider-transaction \
  -d groupId=org.littlewings \
  -d artifactId=database-rider-transaction \
  -d version=0.0.1-SNAPSHOT \
  -d packageName=org.littlewings.spring.dbrider \
  -d dependencies=jdbc,mysql \
  -d baseDir=database-rider-transaction | tar zxvf -

ディレクトリ内に移動。

$ cd test-execution-listener-example

生成されたMaven依存関係など。

        <properties>
                <java.version>17</java.version>
        </properties>
        <dependencies>
                <dependency>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-jdbc</artifactId>
                </dependency>

                <dependency>
                        <groupId>com.mysql</groupId>
                        <artifactId>mysql-connector-j</artifactId>
                        <scope>runtime</scope>
                </dependency>
                <dependency>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-test</artifactId>
                        <scope>test</scope>
                </dependency>
        </dependencies>

        <build>
                <plugins>
                        <plugin>
                                <groupId>org.springframework.boot</groupId>
                                <artifactId>spring-boot-maven-plugin</artifactId>
                        </plugin>
                </plugins>
        </build>

自動生成されたソースコードは削除しておきます。

$ rm src/main/java/org/littlewings/spring/dbrider/DatabaseRiderTransactionApplication.java src/test/java/org/littlewings/spring/dbrider/DatabaseRiderTransactionApplicationTests.java

今回は、動作の違いがわかるようにRider JUnit 5モジュールとRider Springモジュールの両方を追加します。

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.github.database-rider</groupId>
            <artifactId>rider-junit5</artifactId>
            <version>1.36.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.github.database-rider</groupId>
            <artifactId>rider-spring</artifactId>
            <version>1.36.0</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

ここから動作確認用のソースコードとテストコードを書いていきましょう。

お題とソースコード

今回使うテーブルは以下の2つとします。

src/main/resources/schema.sql

drop table if exists person;
drop table if exists family;

create table family(
  id int,
  name varchar(20),
  primary key(id)
);

create table person(
  id int,
  last_name varchar(20),
  first_name varchar(20),
  age int,
  family_id int,
  primary key(id),
  foreign key(family_id) references family(id)
);

ここに、初期データとして以下を加えるようにします。

src/main/resources/data.sql

-- family
insert into family(id, name)
values(1, '磯野家');

-- people
insert into person(id, last_name, first_name, age, family_id)
values(1, '磯野', '波平', 55, 1);
insert into person(id, last_name, first_name, age, family_id)
values(2, '磯野', 'フネ', 48, 1);

この2つのSQLは、いずれもSpring Bootの起動時に自動で実行されるように設定します。

src/main/resources/application.properties

spring.datasource.url=jdbc:mysql://172.17.0.2:3306/practice?characterEncoding=utf-8&connectionCollation=utf8mb4_0900_bin
spring.datasource.username=kazuhira
spring.datasource.password=password

spring.sql.init.mode=always

この初期データが入った状態で、テストコード内でデータを追加しアサーションを行い、Database Riderとしてもアサーションを
行うようにします。ここで、@Transactionalをテストメソッドに付与するとRider JUnit 5モジュールとRider Springモジュールで
動きがどう変わるかを確認するのが今回のお題です。

ソースコードの作成。

エンティティ的なクラス。

src/main/java/org/littlewings/spring/dbrider/Family.java

package org.littlewings.spring.dbrider;

public class Family {
    private Integer id;
    private String name;

    public static Family create(Integer id, String name) {
        Family family = new Family();
        family.setId(id);
        family.setName(name);

        return family;
    }

    // getter/setterは省略
}

src/main/java/org/littlewings/spring/dbrider/Person.java

package org.littlewings.spring.dbrider;

public class Person {
    private Integer id;
    private String lastName;
    private String firstName;
    private Integer age;
    private Integer familyId;

    public static Person create(Integer id, String lastName, String firstName, Integer age, Integer familyId) {
        Person person = new Person();
        person.setId(id);
        person.setLastName(lastName);
        person.setFirstName(firstName);
        person.setAge(age);
        person.setFamilyId(familyId);

        return person;
    }

    // getter/setterは省略
}

Serviceクラス。

src/main/java/org/littlewings/spring/dbrider/PersonService.java

package org.littlewings.spring.dbrider;

import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

@Service
@Transactional
public class PersonService {
    NamedParameterJdbcTemplate jdbcTemplate;

    public PersonService(NamedParameterJdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    public void addFamily(Family family, List<Person> people) {
        addFamily(family);

        addPeople(people);
    }

    public void addPeople(List<Person> people) {
        people.forEach(this::addPerson);
    }

    public void addFamily(Family family) {
        jdbcTemplate.update("""
                insert into family(id, name)
                values(:id, :name)""", new BeanPropertySqlParameterSource(family));
    }

    public void addPerson(Person person) {
        jdbcTemplate.update("""
                insert into person(id, last_name, first_name, age, family_id)
                values(:id, :lastName, :firstName, :age, :familyId)""", new BeanPropertySqlParameterSource(person));
    }

    public int countPeopleByFamily(Integer familyId) {
        return jdbcTemplate.queryForObject("""
                select count(*)
                from person
                where family_id = :familyId""",
                Map.of("familyId", familyId),
                Integer.class);
    }

    public int countFamily() {
        return jdbcTemplate.queryForObject("""
                select count(*)
                from family""",
                Map.of(),
                Integer.class);
    }
}

mainメソッドを持ったクラス。

src/main/java/org/littlewings/spring/dbrider/App.java

package org.littlewings.spring.dbrider;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class App {
    public static void main(String... args) {
        SpringApplication.run(App.class, args);
    }
}

以上で準備は完了です。

テストコードを書く

では、テストコードを作成します。

src/test/java/org/littlewings/spring/dbrider/DatabaseRiderTest.java

package org.littlewings.spring.dbrider;

import com.github.database.rider.core.api.dataset.DataSet;
import com.github.database.rider.core.api.dataset.ExpectedDataSet;
import com.github.database.rider.core.api.dataset.SeedStrategy;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest
//@com.github.database.rider.spring.api.DBRider
//@com.github.database.rider.junit5.api.DBRider
public class DatabaseRiderTest {
    @Autowired
    PersonService personService;

    @Test
    //@Transactional
    @DataSet(
            value = "org/littlewings/spring/dbrider/DatabaseRiderTest/load_dataSet.yml",
            strategy = SeedStrategy.INSERT
    )
    @ExpectedDataSet(
            value = "org/littlewings/spring/dbrider/DatabaseRiderTest/expected_dataSet.yml",
            orderBy = "id"
    )
    void addFamily() {
        List<Person> additionalIsonoPeople = List.of(
                Person.create(5, "磯野", "カツオ", 11, 1),
                Person.create(6, "磯野", "ワカメ", 9, 1),
                Person.create(7, "フグ田", "タラオ", 3, 1)
        );

        personService.addPeople(additionalIsonoPeople);

        Family naminoFamily = Family.create(2, "波野家");

        List<Person> naminoPeople = List.of(
                Person.create(8, "波野", "ノリスケ", 24, 2),
                Person.create(9, "波野", "タイコ", 22, 2),
                Person.create(10, "波野", "イクラ", 1, 2)
        );

        personService.addFamily(naminoFamily, naminoPeople);

        assertThat(personService.countFamily())
                .isEqualTo(2);
        assertThat(personService.countPeopleByFamily(1))
                .isEqualTo(7);
        assertThat(personService.countPeopleByFamily(2))
                .isEqualTo(3);

    }
}

テストコード内で、Database Riderによってロードされたデータを前提としたアサーションは、テストコード内でのデータ追加を
行っています。

コメントアウトしているところは、使用するRiderモジュールによって切り替えていきます。

テスト開始時には、以下のデータセットをロードします。

src/test/resources/org/littlewings/spring/dbrider/DatabaseRiderTest/load_dataSet.yml

person:
  - id: 3
    last_name: "フグ田"
    first_name: "サザエ"
    age: 23
    family_id: 1
  - id: 4
    last_name: "フグ田"
    first_name: "マスオ"
    age: 32
    family_id: 1

アサーションは、以下のデータセットに対して行います。

src/test/resources/org/littlewings/spring/dbrider/DatabaseRiderTest/expected_dataSet.yml

family:
  - id: 1
    name: "磯野家"
  - id: 2
    name: "波野家"
person:
  - id: 1
    last_name: "磯野"
    first_name: "波平"
    age: 55
    family_id: 1
  - id: 2
    last_name: "磯野"
    first_name: "フネ"
    age: 48
    family_id: 1
  - id: 3
    last_name: "フグ田"
    first_name: "サザエ"
    age: 23
    family_id: 1
  - id: 4
    last_name: "フグ田"
    first_name: "マスオ"
    age: 32
    family_id: 1
  - id: 5
    last_name: "磯野"
    first_name: "カツオ"
    age: 11
    family_id: 1
  - id: 6
    last_name: "磯野"
    first_name: "ワカメ"
    age: 9
    family_id: 1
  - id: 7
    last_name: "フグ田"
    first_name: "タラオ"
    age: 3
    family_id: 1
  - id: 8
    last_name: "波野"
    first_name: "ノリスケ"
    age: 24
    family_id: 2
  - id: 9
    last_name: "波野"
    first_name: "タイコ"
    age: 22
    family_id: 2
  - id: 10
    last_name: "波野"
    first_name: "イクラ"
    age: 1
    family_id: 2

DbUnitの設定。

src/test/resources/dbunit.yml

properties:
  caseSensitiveTableNames: true

データベース接続の設定は、Spring Bootの設定をものが使われます。

Rider JUnit 5モジュールを使う

最初は、Rider JUnit 5モジュールを使いましょう。

こちらを使います。

@SpringBootTest
@com.github.database.rider.junit5.api.DBRider
public class DatabaseRiderTest {

@Transactionalはなしでいきます。

    @Test
    // @Transactional
    @DataSet(
            value = "org/littlewings/spring/dbrider/DatabaseRiderTest/load_dataSet.yml",
            strategy = SeedStrategy.INSERT
    )
    @ExpectedDataSet(
            value = "org/littlewings/spring/dbrider/DatabaseRiderTest/expected_dataSet.yml",
            orderBy = "id"
    )
    void addFamily() {

このテストは、問題なく成功します。

テスト終了時に、データは残ったままになります。

 MySQL  localhost:3306 ssl  practice  SQL > select * from family;
+----+-----------+
| id | name      |
+----+-----------+
|  1 | 磯野家 |
|  2 | 波野家 |
+----+-----------+
2 rows in set (0.0004 sec)


 MySQL  localhost:3306 ssl  practice  SQL > select * from person;
+----+-----------+--------------+-----+-----------+
| id | last_name | first_name   | age | family_id |
+----+-----------+--------------+-----+-----------+
|  1 | 磯野    | 波平       |  55 |         1 |
|  2 | 磯野    | フネ       |  48 |         1 |
|  3 | フグ田 | サザエ    |  23 |         1 |
|  4 | フグ田 | マスオ    |  32 |         1 |
|  5 | 磯野    | カツオ    |  11 |         1 |
|  6 | 磯野    | ワカメ    |   9 |         1 |
|  7 | フグ田 | タラオ    |   3 |         1 |
|  8 | 波野    | ノリスケ |  24 |         2 |
|  9 | 波野    | タイコ    |  22 |         2 |
| 10 | 波野    | イクラ    |   1 |         2 |
+----+-----------+--------------+-----+-----------+
10 rows in set (0.0006 sec)

では、テストメソッドに@Transactionalアノテーションを付与してみます。

    @Test
    @Transactional
    @DataSet(
            value = "org/littlewings/spring/dbrider/DatabaseRiderTest/load_dataSet.yml",
            strategy = SeedStrategy.INSERT
    )
    @ExpectedDataSet(
            value = "org/littlewings/spring/dbrider/DatabaseRiderTest/expected_dataSet.yml",
            orderBy = "id"
    )
    void addFamily() {

すると、このテストは失敗します。

2023-03-25T20:05:39.974+09:00 ERROR 32950 --- [           main] org.dbunit.assertion.DbUnitAssertBase    : org.dbunit.assertion.DbComparisonFailure[row count (table=family)expected:<2>but was:<1>]

row count (table=family) expected:<2> but was:<1>
Comparison Failure: 
Expected :2
Actual   :1
<Click to see difference>

org.dbunit.assertion.DbComparisonFailure[row count (table=family)expected:<2>but was:<1>]
    at org.dbunit.assertion.DefaultFailureHandler$DefaultFailureFactory.createFailure(DefaultFailureHandler.java:323)
    at org.dbunit.assertion.DefaultFailureHandler.createFailure(DefaultFailureHandler.java:105)
    at org.dbunit.assertion.DbUnitAssertBase.compareRowCounts(DbUnitAssertBase.java:171)
    at org.dbunit.assertion.DbUnitAssertBase.assertWithValueComparer(DbUnitAssertBase.java:417)
    at org.dbunit.assertion.DbUnitAssert.assertEquals(DbUnitAssert.java:300)
    at org.dbunit.assertion.DbUnitAssert.assertEquals(DbUnitAssert.java:268)
    at org.dbunit.assertion.DbUnitAssert.assertEquals(DbUnitAssert.java:227)
    at org.dbunit.assertion.DbUnitAssert.assertEqualsIgnoreCols(DbUnitAssert.java:103)
    at com.github.database.rider.core.assertion.DataSetAssertion.assertEqualsIgnoreCols(DataSetAssertion.java:17)
    at com.github.database.rider.core.dataset.DataSetExecutorImpl.compareClassic(DataSetExecutorImpl.java:877)
    at com.github.database.rider.core.dataset.DataSetExecutorImpl.compareCurrentDataSetWith(DataSetExecutorImpl.java:835)
    at com.github.database.rider.core.RiderRunner.performDataSetComparison(RiderRunner.java:144)
    at com.github.database.rider.core.RiderRunner.runAfterTest(RiderRunner.java:63)
    at com.github.database.rider.junit5.DBUnitExtension.afterTestExecution(DBUnitExtension.java:79)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeAfterTestExecutionCallbacks$9(TestMethodTestDescriptor.java:236)

〜省略〜

つまり、Rider JUnit 5モジュールを使うと、@Transactionalアノテーションとは組み合わせられないことになります。

Rider Springモジュール

次に、Rider Springモジュールと組み合わせるとどうなるかを見ていきます。

こちらを使います。

@SpringBootTest
@com.github.database.rider.spring.api.DBRider
public class DatabaseRiderTest {

@Transactionalはなしでいきます。

    @Test
    // @Transactional
    @DataSet(
            value = "org/littlewings/spring/dbrider/DatabaseRiderTest/load_dataSet.yml",
            strategy = SeedStrategy.INSERT
    )
    @ExpectedDataSet(
            value = "org/littlewings/spring/dbrider/DatabaseRiderTest/expected_dataSet.yml",
            orderBy = "id"
    )
    void addFamily() {

このテストは、問題なく成功します。

テスト終了時に、データは残ったままになります。

 MySQL  localhost:3306 ssl  practice  SQL > select * from family;
+----+-----------+
| id | name      |
+----+-----------+
|  1 | 磯野家 |
|  2 | 波野家 |
+----+-----------+
2 rows in set (0.0004 sec)


 MySQL  localhost:3306 ssl  practice  SQL > select * from person;
+----+-----------+--------------+-----+-----------+
| id | last_name | first_name   | age | family_id |
+----+-----------+--------------+-----+-----------+
|  1 | 磯野    | 波平       |  55 |         1 |
|  2 | 磯野    | フネ       |  48 |         1 |
|  3 | フグ田 | サザエ    |  23 |         1 |
|  4 | フグ田 | マスオ    |  32 |         1 |
|  5 | 磯野    | カツオ    |  11 |         1 |
|  6 | 磯野    | ワカメ    |   9 |         1 |
|  7 | フグ田 | タラオ    |   3 |         1 |
|  8 | 波野    | ノリスケ |  24 |         2 |
|  9 | 波野    | タイコ    |  22 |         2 |
| 10 | 波野    | イクラ    |   1 |         2 |
+----+-----------+--------------+-----+-----------+
10 rows in set (0.0006 sec)

では、テストメソッドに@Transactionalアノテーションを付与してみます。

    @Test
    @Transactional
    @DataSet(
            value = "org/littlewings/spring/dbrider/DatabaseRiderTest/load_dataSet.yml",
            strategy = SeedStrategy.INSERT
    )
    @ExpectedDataSet(
            value = "org/littlewings/spring/dbrider/DatabaseRiderTest/expected_dataSet.yml",
            orderBy = "id"
    )
    void addFamily() {

Rider JUnit 5モジュールと異なり、このテストは成功します。

また、データはロールバックされています。

 MySQL  localhost:3306 ssl  practice  SQL > select * from family;
+----+-----------+
| id | name      |
+----+-----------+
|  1 | 磯野家 |
+----+-----------+
1 row in set (0.0010 sec)


 MySQL  localhost:3306 ssl  practice  SQL > select * from person;
+----+-----------+------------+-----+-----------+
| id | last_name | first_name | age | family_id |
+----+-----------+------------+-----+-----------+
|  1 | 磯野    | 波平     |  55 |         1 |
|  2 | 磯野    | フネ     |  48 |         1 |
+----+-----------+------------+-----+-----------+
2 rows in set (0.0012 sec)

正確には、data.sqlでロードしたものだけが残り、Database Riderおよびテストコード内で追加したデータについてはロールバック
されています。

どうしてこうなるのか?

どうしてこういう差が出るのかは、2つのモジュールの基礎になっている仕組みの差が出ています。

Rider JUnit 5モジュールは、JUnit 5のテストライフサイクルコールバックの仕組みで実現されているのでした。

JUnit 5 User Guide / Extension Model / Test Lifecycle Callbacks

https://github.com/database-rider/database-rider/blob/1.36.0/rider-junit5/src/main/java/com/github/database/rider/junit5/api/DBRider.java

https://github.com/database-rider/database-rider/blob/1.36.0/rider-junit5/src/main/java/com/github/database/rider/junit5/DBUnitExtension.java

実行タイミングはSpring Testの@Transactionalの実行の仕組みであるTestExecutionListenerよりも後(テストメソッド実行後は前)に
なるのですが、Spring Testの実行時に使うデータベース接続とは別の接続を使うことになります。

このため、Database Riderによるアサーション時にはテストメソッドで登録したデータは見えないのです。

これは、このエントリーを書いた時にも調べていました。

Database RiderをSpring Framework(Spring Boot)と合わせて使う - CLOVER🍀

https://github.com/database-rider/database-rider/blob/1.36.0/rider-junit5/src/main/java/com/github/database/rider/junit5/jdbc/ConnectionManager.java#L51

Rider Springモジュールの場合は、@Transactionalの実行の仕組みであるTestExecutionListenerを使って実現されており、
かつ適用される順番が最も遅い(AbstractTestExecutionListenerのデフォルト値)ため@Transactionalで開始されたトランザクション内で
実行されることになります。

このため、データベース接続も同じものが使われます。

たとえば、今回のテストコードを実行する前提で以下の設定をapplication.propertiesに追加すると、Rider JUnit 5モジュールを
使っている場合はDatabase Riderがデータベース接続を取得できず実行に失敗しますが、Rider Springモジュールを使っている場合は
問題なく実行できます。

spring.datasource.hikari.maximum-pool-size=1

どうしましょう?

Rider Springモジュールの中身を見ると、README.mdにはSpringRunner向けの設計だと書かれていたものの、具体的に依存している
仕組みはTestExecutionListenerなのでこの点については問題ないのかなと思います。

ただ、Rider SpringモジュールはJUnit 5向けのモジュールではないことは間違いありません。

よって、Rider Springモジュールを使用した状態で、サンプルにあるようなJUnit 5のテストライフサイクルメソッドに対して
@DataSetアノテーション等を利用しても効果がありません。

    @BeforeAll
    @DataSet("emptyUsers.yml")
    static void beforeAll() {}

    @BeforeEach
    @DataSet("users.yml")
    public void setUpUsers() {
    }

https://github.com/database-rider/database-rider/blob/1.36.0/rider-examples/spring-boot-dbunit-sample/src/test/java/com/github/database/rider/springboot/SpringBootDBUnitTest.java

JUnit 5向けの機能か、@Transactionalとの組み合わせを重視するかが選択のポイントになりそうですね。

まとめ

Database RiderをSpring Framework(Spring Boot)と合わせて使う時に、組み合わせるのがRider JUnit 5モジュールなのか
Rider Springモジュールなのかで@Transactionalをテストメソッドに付与した時に挙動が変わることを調べてみました。

データセットを用意するやり方だと@Transactinalでのロールバックは効いて欲しいような気もするのですが、どうなのでしょうね。