easyb で dbunit - easyb dbunit プラグイン使用
easyb の dbunit(DBのユニットテストツール)用のプラグインを使ってみる事にする。
ちなみに、dbunit プラグインを使うと database_model メソッド(クロージャで DB に格納する初期レコードを指定できる)が使えるようになる。
使用した環境は以下の通り。
振る舞いの定義
では、easyb で振る舞いを定義する。今回は簡単な DB へのアクセス用 Java クラスを振る舞いの定義対象とした。
ここで、dbunit プラグインによって追加される database_model はクロージャが返す XML 文字列を使って DB の初期レコードを設定する機能を有している。
ただし、デフォルト文字コードでバイト配列化したデータを使って FlatXmlDataSet(dbunit のクラス)を作成し、DB にレコード登録するため、HSQLDB に日本語文字列を格納する点で不都合が生じる。
今回は、これを回避するための措置として、dbunit プラグインの FlatXmlDataSet を生成している処理を上書きし、UTF-8 の XML を取り込むようにした。
ちなみに、XML の生成には Groovy の MarkupBuilder を使用した。
dataDao.story ファイル
import java.sql.DriverManager import groovy.sql.Sql import groovy.xml.MarkupBuilder import org.dbunit.dataset.xml.FlatXmlDataSet import org.disco.easyb.plugin.delegates.DBUnitDelegate import sample.DataDao //HSQLDB に日本語(UTF-8 で)を格納させるための措置 DBUnitDelegate.metaClass.getDataSet = {Closure model -> data = model.call() as String new FlatXmlDataSet(new ByteArrayInputStream(data.getBytes("UTF-8"))) } dburl = "jdbc:hsqldb:./db/test1" driver = "org.hsqldb.jdbcDriver" user = "sa" password = "" scenario "データを検索する", { given "DBスキーマ定義", { sql = Sql.newInstance(dburl, user, password, driver) ddl = """ DROP TABLE data IF EXISTS; CREATE TABLE data(ID INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 1) NOT NULL PRIMARY KEY, NAME VARCHAR(50), POINT INTEGER NOT NULL); COMMIT; """ sql.execute(ddl) } and "初期データ", { //dbunit プラグインで追加される機能を使用 database_model(driver, dburl, user, password) { def writer = new StringWriter() def builder = new MarkupBuilder(writer) //XML の定義 builder.dataset() { data(name: "テスター1", point: 10) data(name: "fits", point: 5) } //XML を生成 writer.toString() } } when "DB検索クラスのインスタンス作成", { dbObj = new DataDao(DriverManager.getConnection(dburl, user, password)) } then "test1 の検索結果数は 1 になるはず", { resultList = dbObj.searchWithName("テスター1") resultList.size.shouldBe 1 } and "id は 1、point は 10 になるはず", { resultList[0].id.shouldBe 1 resultList[0].point.shouldBe 10 } }
Java クラスは以下の通り。
DataDao.java ファイル
package sample; import java.sql.*; import java.util.ArrayList; import java.util.List; public class DataDao { private Connection con; public DataDao(Connection con) { this.con = con; } public List<Data> searchWithName(String name) { ArrayList<Data> result = new ArrayList<Data>(); try { PreparedStatement ps = this.con.prepareStatement("select * from data where name=?"); ps.setString(1, name); ResultSet rs = ps.executeQuery(); while (rs.next()) { Data data = new Data(); data.id = rs.getInt("id"); data.name = rs.getString("name"); data.point = rs.getInt("point"); result.add(data); } } catch (SQLException ex) { } return result; } }
Data.java ファイル
package sample; public class Data { public int id; public String name; public int point; }
easyb 実行
Gant を使って easyb を実行。
src ディレクトリに Java ソースファイル、spec ディレクトリに easyb ソースファイルを配置している。
build.gant ファイル
srcDir = "src" destDir = "dest" specDir = "spec" includeTargets << gant.targets.Clean cleanDirectory << destDir target("default": null) { path(id: "project.classpath") { pathelement(path: "$destDir") fileset(dir: "c:/easyb-0.9") { include(name: "**/*.jar") } fileset(dir: "c:/easyb-dbunit-plugin-0.9") { include(name: "**/*.jar") } //Grails 内の HSQLDB を使用 fileset(dir: "c:/grails-1.0.3/lib") { include(name: "**/*.jar") } } taskdef(name: "easyb", classname: "org.disco.easyb.ant.BehaviorRunnerTask") { classpath(refid: "project.classpath") } mkdir(dir: "$destDir") javac(srcdir: "$srcDir", destdir: "$destDir") { classpath(refid: "project.classpath") } easyb { classpath(refid: "project.classpath") behaviors(dir: "$specDir") { include(name: "**/*Story.groovy") include(name: "**/*.story") include(name: "**/*Specification.groovy") include(name: "**/*.specification") } } }
実行結果
>gant ・・・ [easyb] easyb is preparing to process 1 file(s) [easyb] Running data scenario story story (dataDao.story) [easyb] Scenarios run: 1, Failures: 0, Pending: 0, Time Elapsed: 1.332 sec [easyb] 1 behavior run with no failures [easyb] easyb execution passed