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クラスに対するテストなどに限られるだろう。