S2UnitでDB挿入のテスト - DBの内容をExcelに書き出す

Seasar2では、SqlReaderとXlsWriterというクラスが用意されていて、DBのテストが簡単に行えるようになっている。

使い方

重要な部分だけみるとこれだけ。

XlsWriter writer = new XlsWriter("FILE_PATH");
sqlReader.addTable("EMPLOYEE");
sqlReader.addTable("DEPARTMENT");
writer.write(sqlReader.read());
  • 出力するExcelファイルのパスを指定してXlsWriterを生成する。
  • Excelに出力したいテーブルの名前を、SqlReader.addTable("tableName")で追加。
  • SqlReader.read()でDataSetを取得し、それをXlsWriter.write()で書込み。

これはExcelに出力して確認する方法になるので、自動化ではなく目視による確認ということになる。まだ試していないが、SqlReader.read()で取得したDataSetと、テーブルの内容を表現したExcelファイルとの比較(assert)も出来るらしい。テスティングフレームワークでテストを行う一番のメリットはテストの自動化なので、多少手間がかかってもそうすべきかもしれない(このあたりはプロジェクトによりけりだろう)。

今回書いたソース

EmployeeTest(テストクラス)
public class EmployeeTest extends S2TestCase {

	private static final String TEST_DIR = "c:/aaa/bbb/";

	private JdbcManager jdbcManager;

	private SqlReader reader;

	public void setUp() {
		include("test.dicon");
	}

	public void testInsertTx() {

		Department department = new Department();
		department.departmentName = "Dept.A";
		jdbcManager.insert(department).execute();

		Employee employee = new Employee();
		employee.departmentId	= department.departmentId;
		employee.employeeName	= "Emp.A";
		employee.birthDay		= new Date();
		jdbcManager.insert(employee).execute();

		XlsWriter writer = new XlsWriter(new File(TEST_DIR + "testInsert.xls"));
		reader.addTable("Department");
		reader.addTable("Employee");
		writer.write(reader.read());
	}
}
test.dicon(includeしているdiconファイル)
<components>
	<include path="app.dicon" />
	<component class="org.seasar.extension.dataset.impl.SqlReader" />
</components>

SqlReaderをdiconで定義しているのは、SqlReaderの生成にDataSourceインターフェースが必要なため。DataSourceはjdbc.diconに定義してあるので、こうして単にコンポーネントの定義だけ書いておけば、勝手にインジェクションしてくれる。

Employee(エンティティ)
@Entity
public class Employee {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	public Integer employeeId;

	public Integer departmentId;
//	public Integer departmentDepartmentId;

	public String employeeName;

	@Temporal(TemporalType.DATE)
	public Date birthDay;

	@ManyToOne
	@JoinColumn(name = "DEPARTMENT_ID")
	public Department department;
}

@ManyToOneを指定する場合、自身に外部キーを格納するプロパティ(今回はdepartmentId)を定義しておかなければならないのだが、これはデフォルト(@JoinColumnの指定なし)では、"{テーブル名}_{主キー}"というプロパティとみなされるらしい。今回、部署テーブルの主キーはDEPARTMENT_IDとしている為、デフォルトで動作させようと思ったら、departmentDepartmentIdというプロパティにしなければならないようだ。これを間違えていると以下のようなエラーが出るので注意。

org.seasar.extension.jdbc.exception.ManyToOneFKNotFoundRuntimeException: [ESSR0729]エンティティ(Employees)のプロパティ(departments)が不正です。JoinColumnのnameで指定されている外部キー(DEPARTMENTS_DEPARTMENT_ID)が存在しません。
Department(エンティティ)
@Entity
public class Department {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	public Integer departmentId;

	public String departmentName;

	@OneToMany(mappedBy = "department")
	public List<Employee> employeeList;
}
補足

今回は、jdbcManager.insert()をした後、正しくテーブルが更新されているかを確認しているが、実際にこうしたテストはほとんど意味が無い。挿入系で単体テストをやるとしたら、複数のテーブルにレコードを同時に作成するServiceクラスに対するテストなどに限られるだろう。