DBUnitとH2 Databaseを使ってみた。
「JUnit実践入門 ~体系的に学ぶユニットテストの技法」を参考にしてDAOのテストケースを作成したのでメモ。
JunitをベースにDBUnit、H2 Databaseを使ってテストしました。
本番で稼働させているのはMySQLなんですが、単体テストのときはテスト環境に依存しないようにH2 Databaseを使用しようかなと。
H2 Databaseとは?
詳しくは こちら(wiki) 。
Pure Javaでjarファイル1つあれば動きます。データはファイルで保存されます。SQLiteみたい。
早いとの触れ込みですが、実際のところはどうなのでしょうか?あんまり使われているという話は聞かないですね。
jarの入手ですが、僕はMavenを使っているので以下のように設定しました。
pom.xml
<dependency> <groupId>org.dbunit</groupId> <artifactId>dbunit</artifactId> <version>2.4.7</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.5.6</version> </dependency>
最新版はこちら を参照してください。
DBUnitとは?
詳しくは こちら(公式サイト) 。
DB接続系クラスのテストフレームワークです。
こちらもMavenで以下のように設定しました。
pom.xml
<dependency> <groupId>org.dbunit</groupId> <artifactId>dbunit</artifactId> <version>2.4.7</version> </dependency>
最新版はこちら を参照してください。
JUnit実践入門を参考に以下のようにクラスを作ってみました。
DbUnitTester.java
package hoge; import java.sql.Connection; import java.sql.DriverManager; import org.dbunit.AbstractDatabaseTester; import org.dbunit.database.DatabaseConfig; import org.dbunit.database.DatabaseConnection; import org.dbunit.database.IDatabaseConnection; import org.dbunit.dataset.IDataSet; import org.dbunit.ext.h2.H2DataTypeFactory; import org.junit.rules.TestRule; import org.junit.runner.Description; import org.junit.runners.model.Statement; public abstract class DbUnitTester extends AbstractDatabaseTester implements TestRule { private final String connectionUrl; private final String username; private final String password; public DbUnitTester(String driverClass, String connectionUrl) { this(driverClass, connectionUrl, null, null); } public DbUnitTester(String driverClass, String connectionUrl, String username, String password) { this(driverClass, connectionUrl, username, password, null); } public DbUnitTester(String driverClass, String connectionUrl, String username, String password, String schema) { super(schema); this.connectionUrl = connectionUrl; this.username = username; this.password = password; assertNotNullNorEmpty("driverClass", driverClass); try { // JDBCドライバのロード Class.forName(driverClass); } catch (ClassNotFoundException e) { throw new AssertionError(e); } } @Override public IDatabaseConnection getConnection() throws Exception { Connection conn = null; if (username == null && password == null) { conn = DriverManager.getConnection(connectionUrl); } else { conn = DriverManager.getConnection(connectionUrl, username, password); } DatabaseConnection dbConnection = new DatabaseConnection(conn, getSchema()); DatabaseConfig config = dbConnection.getConfig(); config.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new H2DataTypeFactory()); return dbConnection; } protected void executeQuery(String sql) throws Exception { Connection conn = getConnection().getConnection(); conn.createStatement().execute(sql); conn.commit(); conn.close(); } protected void before() throws Exception { } protected void after() throws Exception { } abstract protected IDataSet createDataSet() throws Exception; @Override public Statement apply(final Statement base, Description description) { return new Statement() { @Override public void evaluate() throws Throwable { before(); setDataSet(createDataSet()); onSetup(); try { base.evaluate(); } finally { try { after(); } finally { onTearDown(); } } } }; } }
H2DatabaseServer.java
H2 Databaseを起動、停止させるクラス。
package hoge; import java.sql.Connection; import java.util.Properties; import org.h2.tools.Server; import org.h2.util.JdbcUtils; import org.junit.rules.ExternalResource; public class H2DatabaseServer extends ExternalResource { private final String baseDir; private final String dbName; private final String schemaName; private Server server = null; public H2DatabaseServer(String baseDir, String dbName, String schemaName) { this.baseDir = baseDir; this.dbName = dbName; this.schemaName = schemaName; } @Override protected void before() throws Throwable { // DBサーバの起動 server = Server.createTcpServer("-baseDir", baseDir); server.start(); // スキーマの設定 Properties props = new Properties(); props.setProperty("user", "sa"); props.setProperty("password", ""); String url = "jdbc:h2:tcp://localhost/" + dbName; Connection conn = org.h2.Driver.load().connect(url, props); try { conn.createStatement().execute("CREATE SCHEMA IF NOT EXISTS " + schemaName); } finally { JdbcUtils.closeSilently(conn); } } @Override protected void after() { // DBサーバの停止 server.shutdown(); } }