S2EJB3UnitはS2Unitを拡張したテスティングフレームワークです。
S2EJB3UnitはEJB 3.0のコンポーネントとJava Persistence API(JPA)のエンティティに対するテストを効率化します。
S2EJB3Unitには次の特長があります。
- ejb3.diconとhibernate-jpa.diconを自動的にincludeします。
- registerメソッドによりEJB 3.0コンポーネントを組立てることができます。
- Rollbackアノテーションが指定されたテストメソッドの実行前にトランザクションを開始し実行後にトランザクションをロールバックします。
- EntityManagerを返すgetEntityManagerを提供します。
- assertEntityEqualsメソッドもしくはassertEntityListEqualsメソッドによりExcelの期待値データとJPAのエンティティを比較します。
このサンプルでは、従業員の名前を返すServiceのステートレスセッションBeanをテストします。
シナリオとして従業員番号9900で検索をかけると従業員番号9900の従業員名を返すということを想定します。
ServiceのステートレスセッションBeanはDAOのステートレスセッションBeanを呼び出し、DAOのステートレスセッションBeanはデータベースにアクセスします。
データベースのアクセスにはJDBC APIを利用します。
このケースをテストするためには、検索のための従業員テーブルのデータが必要です。
データはExcelで用意します。データの作り方などについては適宜S2Unitのサンプルを参照してください。
ServiceとDAOそれぞれにビジネスインタフェースとステートレスセッションBeanを用意します。
examples.s2ejb3unit.EmployeeService
package examples.s2ejb3unit;
public interface EmployeeService {
String getEmployeeName(int empno);
}
examples.s2ejb3unit.EmployeeServiceImpl
package examples.s2ejb3unit;
import javax.ejb.EJB;
import javax.ejb.Stateless;
@Stateless
public class EmployeeServiceImpl implements EmployeeService {
@EJB
private EmployeeDao dao;
public String getEmployeeName(int empno) {
return dao.getEmployeeName(empno);
}
}
examples.s2ejb3unit.EmployeeDao
package examples.s2ejb3unit;
public interface EmployeeDao {
String getEmployeeName(int empno);
}
examples.s2ejb3unit.EmployeeDaoImpl
package examples.s2ejb3unit;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.sql.DataSource;
@Stateless
public class EmployeeDaoImpl implements EmployeeDao {
@Resource
DataSource ds;
public String getEmployeeName(int empno) {
String ename = null;
try {
Connection con = ds.getConnection();
try {
PreparedStatement ps = con
.prepareStatement("SELECT ename FROM emp WHERE empno = ?");
try {
ps.setInt(1, empno);
ResultSet rs = ps.executeQuery();
try {
if (rs.next()) {
ename = rs.getString("ename");
}
} finally {
rs.close();
}
} finally {
ps.close();
}
} finally {
con.close();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
return ename;
}
}
examples.s2ejb3unit.EmployeeServiceImplTest
package examples.s2ejb3unit;
import javax.ejb.EJB;
import org.seasar.framework.ejb.unit.S2EJB3TestCase;
import org.seasar.framework.unit.annotation.Rollback;
public class EmployeeServiceImplTest extends S2EJB3TestCase {
@EJB
private EmployeeService service;
@Override
public void setUp() throws Exception {
super.setUp();
register(EmployeeDaoImpl.class);
register(EmployeeServiceImpl.class);
}
@Rollback
public void testGetEmployee() throws Exception {
readXlsWriteDb("EmployeeServiceImplTest_getEmployeeName.xls");
assertEquals("1", "SCOTT2", service.getEmployeeName(9900));
}
}
テストクラスはS2EJB3TestCaseを継承します。
setUpメソッド内でregisterメソッドを呼ぶことでEJB 3.0のコンポーネントをコンテナに登録できます(setUpメソッドでは必ずsuper.setUp()を実行してください)。まとめて複数登録する場合や、コンポーネントの組み立て方が複雑な場合はdiconファイルを使い明示的にincludeします。
EJBアノテーションが指定されたフィールドには自動的にEJBのコンポーネントが設定されます。
テストメソッド実行前にトランザクションを開始し、実行後にトランザクションをロールバックしたい場合はテストメソッドにRollbackアノテーションを指定します。
このサンプルでは、従業員エンティティをテストします。
それぞれのテストメソッドでは事前データをデータベースに書き込み、その後エンティティを取得し期待値と比較しています。
public class EmployeeTest extends S2EJB3TestCase {
@Rollback
public void testFindEmployee() {
readXlsWriteDb("Prepare.xls");
DataSet expected = readXls("findEmployeeResult.xls");
Employee actual = getEntityManager().find(Employee.class, new Long(1));
assertEntityEquals("0", expected, actual);
}
@Rollback
public void testFindEmployeeAndRelationship() {
readXlsWriteDb("Prepare.xls");
DataSet expected = readXls("findEmployeeRelationshipsResult.xls");
Employee actual = getEntityManager().find(Employee.class, new Long(1));
assertEntityEquals("0", expected, actual, true);
}
@Rollback
public void testSelectAllEmployees() {
readXlsWriteDb("Prepare.xls");
DataSet expected = readXls("selectAllEmployeesResult.xls");
List actual = getEntityManager().createQuery(
"select e From Employee e").getResultList();
assertEntityListEquals("0", expected, actual);
}
@Rollback
public void testSelectAllEmployeesAndRelationships() {
readXlsWriteDb("Prepare.xls");
DataSet expected = readXls("selectAllEmployeesRelationshipsResult.xls");
List actual = getEntityManager().createQuery(
"select e From Employee e").getResultList();
assertEntityListEquals("0", expected, actual, true);
}
}
getEntityManagerメソッドを使いEntityManagerにアクセスしています。
EntityManagerを取得するにはhibernate-jpa.diconが読み込まれている必要があります。
hibernate-jpa.diconはS2Hibernate-JPAの設定ファイルです。
S2EJB3Unitは現在S2Hibernate-JPAとの連携のみをサポートしています。
S2EJB3TestCaseにはエンティティを期待値のDataSetと比較するためのアサートメソッドが4つ用意されています。
- assertEntityEquals(String message, DataSet expected, Object entity)
- assertEntityEquals(String message, DataSet expected, Object entity, boolean includesRelationships)
- assertEntityListEquals(String message, DataSet expected, Object entity)
- assertEntityListEquals(String message, DataSet expected, Object entity, boolean includesRelationships)
assertEntityEqualsメソッドは単一のエンティティとDataSetを比較します。
assertEntityListEqualsメソッドはエンティティのリストとDataSetを比較します。
assertEntityEqualsメソッドとassertEntityListEqualsメソッドはそれぞれ4つの引数をもつオーバーロードされたメソッドを持ちます。
4番目の引数であるincludesRelationshipsは、比較対象にエンティティのリレーションシップを含めるかどうかのbooleanです。
たとえば従業員エンティティが部門エンティティとリレーションシップをもちassertEntityEqualsメソッドの引数に従業員エンティティが渡されるとき、includesRelationshipsがfalseならば部門エンティティは比較対象になりません。trueのときは比較対象になります。
3つの引数をもつassertEntityEqualsメソッドとassertEntityListEqualsメソッドを利用する場合、includesRelationshipsはfalseだとみなされます。
|