Fight the Future

Java言語とJVM、そしてJavaエコシステム全般にまつわること

意外に知らないDbUnitでCSVを使う方法

dbunit csv」で検索してもヒットしなかったので書いておく。
DbUnit2.1から、初期値や期待値をCSVファイルに書くことができる。XMLやExcelの代わりに。


使い方はとても簡単。

  1. テーブル名.csvというファイルを作成する(EMPテーブルならemp.csv)
  2. CSVファイルの1行目に列名、2行目以降にデータを記述する
  3. 複数のテーブルにデータを入れたい場合、CSVファイルも複数作成する
  4. 「table-ordering.txt」というファイルを作成する
  5. txtファイルに登録するテーブルの順序を記述する(参照整合性制約に反しないように)
  6. CSVファイル、txtファイルを同じディレクトリに配置する
  7. CsvDataSetのコンストラクタにファイルを配置したディレクトリのjava.io.Fileオブジェクトを渡す


たとえば、EMPテーブルがあるとして、emp.csvはこんな感じ。

EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,DEPTNO
7782,CLARK,MANAGER,7839,1981-01-09,2450.0,10

DEPTテーブルのdept.csv。

DEPTNO,DNAME,LOC
10,ACCOUNTING,NEW YORK

EMPテーブルのDEPTNOは、DEPTテーブルを参照しているので、データを登録するときは「DEPT→EMP」の順序にしたい。
なので「table-ordering.txt」はこうなる。

dept
emp

拡張子.csvは必要なし。
CsvDataSetオブジェクトを生成する。

String pathName = "ディレクトリのクラスパスルートからの位置";
URL url =
	Thread
	.currentThread()
	.getContextClassLoader()
	.getResource(pathName);
CsvDataSet dataSet = new CsvDataSet(new File(url.toURI()));


この話、公式サイトにもドキュメントないような。。。
ソースを読むとわかります。

たとえば。

public CsvDataSet(File dir) throws DataSetException {
    super(new CsvProducer(dir));
    this.dir = dir;
}

CsvDataSetのコンストラクタに引数としてdirつまりディレクトリを渡して。

List tableSpecs = CsvProducer.getTables(dir.toURL(), "table-ordering.txt");
for (Iterator tableIter = tableSpecs.iterator(); tableIter.hasNext();) {
    String table = (String) tableIter.next();
    try {
	produceFromFile(new File(dir, table + ".csv"));

table-ordering.txtを行単位で読んで、その行に.csvをつけたファイルを読み込んでる。

private void produceFromFile(File theDataFile) throws DataSetException, CsvParserException {
    logger.debug("produceFromFile(theDataFile=" + theDataFile + ") - start");

    try {
        CsvParser parser = new CsvParserImpl();
        List readData = parser.parse(theDataFile);
        List readColumns = ((List) readData.get(0));
        Column[] columns = new Column[readColumns.size()];

        for (int i = 0; i < readColumns.size(); i++) {
           columns[i] = new Column((String) readColumns.get(i), DataType.UNKNOWN);
        }

(List) readData.get(0)つまりファイルの1行目が列名として扱われてる。