背景
DbSetupはJavaのユニットテストでDBに初期データをロードするのに非常に便利なライブラリです。ただし、大量データや多数の列からなるデータのロードには適しておらず、その場合にはDbUnit等が便利と思われます。これはDbSetupの前提条件である「ユニットテストで必要となるテストデータは大して多くない」というものの現れであり、実際その通りなので、欠点ではありません。
しかしながら、ある種の集計機能だとか、ユニットテストの可読性がテストデータをCSVなど外部ファイルに残した方が見やすい、というケースが稀に発生します。その場合のためだけにDbUnitとか使うのもだるいので、DbSetupだけで済ませる方法は何かないか、と考えました。
解決案
今回取った方法としては、まずテストデータは素直にcsvファイルにします。それから、そのテストデータをH2 Database EngineのCSVREAD関数で読み込み、データロードを行うINSERT INTO ... SELECT * FROM CSVREAD(...)
のSQLを、DbSetupで生のSQLを実行できるOperations#sqlに渡します。
ソースコード
クラスパスの通っている場所に適当なファイルを作ります。
1,かがみ
2,ほげ
3,foo
4,bar
5,piyo
pom.xmlに依存性を追加します。
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.192</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.ninja-squad</groupId>
<artifactId>DbSetup</artifactId>
<version>2.1.0</version>
<scope>test</scope>
</dependency>
</dependencies>
ソースコード。
package kagamihoge.dbsetupwithh2csvread;
import static com.ninja_squad.dbsetup.Operations.sequenceOf;
import static com.ninja_squad.dbsetup.Operations.sql;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.junit.Before;
import org.junit.Test;
import com.ninja_squad.dbsetup.DbSetup;
import com.ninja_squad.dbsetup.destination.DriverManagerDestination;
import com.ninja_squad.dbsetup.operation.Operation;
public class HogeTest {
@Before
public void setUp() throws Exception {
URL csvResource = getClass().getClassLoader().getResource("hoge.csv");
Path csv = Paths.get(csvResource.toURI()).toAbsolutePath();
Operation operation = sequenceOf(
sql("CREATE TABLE hoge(hogeid VARCHAR(16) PRIMARY KEY NOT NULL, hogename VARCHAR(100))"),
sql("INSERT INTO hoge(hogeid, hogename) SELECT * FROM CSVREAD('" + csv + "','hogeid, hogename','UTF-8')"));
DbSetup dbSetup = new DbSetup(
new DriverManagerDestination("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", "sa", ""), operation);
dbSetup.launch();
}
@Test
public void test1() throws SQLException {
// 注意:エラー処理・DBのクローズ処理が適当なので、適宜読み替えて下さい。
Connection con = DriverManager.getConnection("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", "sa", "");
Statement st1 = con.createStatement();
ResultSet rs = st1.executeQuery("SELECT hogeid, hogename FROM hoge");
while (rs.next()) {
System.out.println(rs.getString(1) + "," + rs.getString(2));
}
st1.close();
con.close();
}
}
setUpの最初では、CSVREAD関数に渡すファイルの絶対パスを取得するため、クラスパス上に配置したテストデータのCSVファイル(hoge.csv)から絶対パスを取得しています。
そのあと、DbSetupのOperations#sqlでINSERT INTO ... SELECT * FROM CSVREAD(...)
を実行することで、テストデータのロードを行います。