DB名にスキーマが含まれていると DBUnit の @DatabaseSetup とかでテーブルがみつからない

いや、普通データベースってスキーマ切るでしょ。
これが「DBUnit スキーマ」とかで探してもほとんど出てこなかったんですよ。なんか Oracle データベースの話しかみんなしてない。なんでやねん。

## だめなやつ

```java:TestConfig.java
/**
 * テスト用JDBCドライバのbean
 */
@Configuration
public class TestConfig {
  @Bean
  DataSource dataSource(){
    return dataSourceH2();
  }

  DataSource dataSourceH2() {
    EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
    builder.setType(EmbeddedDatabaseType.H2)
      .addScript("table/schema.sql").addScript("table/data.sql");
    return builder.build();
  }

  @Bean
  JdbcTemplate jdbcTemplate(DataSource dataSource){
    return new JdbcTemplate(dataSource);
  }
}
```

```sql:schema.sql
create schema sh;
create table sh.test
(
    id int
);
```

```sql:data.sql
insert into
  sh.test (id)
  values (1);
```

```:table/init/teble-ordering.txt
sh.test
```

```csv:table/init/sh.test.csv
id
1
2
3
```

```java:Test.java
@SpringBootTest(classes = {TestConfig.class})
@RunWith(SpringRunner.class)
@DbUnitConfiguration(dataSetLoader = CsvDataSetLoader.class) 
@TestExecutionListeners({
  DependencyInjectionTestExecutionListener.class,
  DbUnitTestExecutionListener.class
})
@TestPropertySource("/application.properties")
@Transactional
public class Test {

  @Autowired
  JdbcTemplate jdbcTemplate;

  @Test
  @DatabaseSetup("/table/init") // ← これをコメントアウトするとちゃんとsqlで初期化した内容がプリントされる
  public void test(){
    System.out.println(jdbcTemplate.queryForList("select * from sh.test"));
  }
}
```

`CsvDataSetLoader` の中身は割愛。CSV読めるようにするやつ。

とにかく、 `jdbcTemplate` から `<スキーマ名>.<テーブル名>` でアクセスできるもんだからDBUnitからでも同じ感じでアクセスできるもんだと勘違いしていたけどどうにもエラーが出て初期化をしてくれない。

```
org.dbunit.dataset.NoSuchTableException: sh.test
```

## 探した探した。

https://stackoverflow.com/questions/22796147/spring-test-dbunit-and-table-schema-name

この stackoverflow は最初の方にみつけてはいたものの、ベストアンサーが「`OracleConnection bean` を使え」という物だったから「違うんだよなぁH2なんだよなぁ」と思いながらスルーしていた。けど近しいものがこの質問ぐらいしか無かったから繁々と眺めていたら下の方に少し詳しい回答がちゃんとあった。 ~~飛び道具をベストアンサーにするなよfxxk~~ 

>If you are using the spring-test-dbunit then you need to create an IDatabaseConnection with a specific DBUnit configuration. Following the doc's example I've setup this one for me:
> (spring-test-dbunitを使用している場合は、特定のDBUnit構成でIDatabaseConnectionを作成する必要があります。ドキュメントの例に従って、これをセットアップしました。)

書いてあるのはポスグレ。けれどなんとなくちゃんと設定するものがどこかにあって適切に `@DbUnitConfiguration` に入れてあげればいいのかなぁと思いながら [DBUnitのJavadoc]
(https://javadoc.io/doc/org.dbunit/dbunit/latest/index.html) にそれっぽいの無いかなぁ。 `H2` って名前のついた `IDataConnection` 持ってるクラス無いかなぁ。って思ってたら [ちゃんとありました](https://javadoc.io/doc/org.dbunit/dbunit/latest/org/dbunit/ext/h2/H2Connection.html)。

> public class H2Connection
> Constructor and Description
> H2Connection(java.sql.Connection connection, java.lang.String schema) 

スキーマ指定できるやーん……

## うごくやつ

```java:TestConfig.java
@Configuration
public class TestConfig {
  @Bean
  DataSource dataSource(){
    return dataSourceH2();
  }

  DataSource dataSourceH2() {
    EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
    builder.setType(EmbeddedDatabaseType.H2).addScript("table/scheme.sql").addScript("table/data.sql");
    return builder.build();
  }

  @Bean
  JdbcTemplate jdbcTemplate(DataSource dataSource){
    return new JdbcTemplate(dataSource);
  }

  // DBUnit専用の接続設定を追加
  @Bean
  H2Connection h2Connection() throws DatabaseUnitException, SQLException{
    return new H2Connection(dataSource().getConnection(), "sh");
  }

}

```

```:table/init/teble-ordering.txt
test
```

```csv:table/init/test.csv
id
1
2
3
```
(↑ファイル名変えただけ)

```java:Test.java
@SpringBootTest(classes = {TestConfig.class})
@RunWith(SpringRunner.class)
// databaseConnection に接続設定を追加
@DbUnitConfiguration(databaseConnection = "h2Connection", dataSetLoader = CsvDataSetLoader.class) 
@TestExecutionListeners({
  DependencyInjectionTestExecutionListener.class,
  DbUnitTestExecutionListener.class
})
@TestPropertySource("/application.properties")
@Transactional
public class JsonDatabaseTest {

  @Autowired
  JdbcTemplate jdbcTemplate;

  @Test
  @DatabaseSetup("/table/init")
  public void test(){
    System.out.println(jdbcTemplate.queryForList("select * from sh.test"));
    // ちゃんとCSVの内容が表示される！！！
  }
}
```

めでたしめでたし。


~~なんでJDBCと同じ方法でアクセスさせてくれないんですかねぇ！！！！！~~