Cayenne(3.0.2)でUnitTestするときにテスト用のデータソースを設定する
Apache CayenneでUnitテストを実行する際のガイドが下記ページにあります。
ここで、UnitTestのときにデータソースを切り替える方法が書かれていて、"-DcayenneTestConnection"もしくは"-Dcayenne.test.connection"を使うとなっています。が、これがうまく行きません。
考えた末、別の方法でやることにしました。
実行環境は、OS=Win7HomePremiumと下記。
ソフト | バージョン |
---|---|
JDK | 1.6.0_29 |
Maven | 3.0.3 |
Wicket | 1.5.3 |
Cayenne | 3.0.2 |
設定方法は、 (Apache) Wicket+CayenneでWebアプリを参照。
前提
WicketのWicketTesterでassertRenderedPageを使ってテストします。「ページを初期表示する際にデータベースから先頭10件を表示する」という機能のページがあったとして、そのテストを実行するとCayenneで動作する部分も動きます。
運用環境はJDBCデータソースで接続先を決定していますので、DataSourceFactoryは"JNDIDataSourceFactory"に設定されています。単体で実行するときにはJNDIを使いたくないor使えないので、このときだけ別の接続設定を適用したい。ただし、煩雑かつ誤登録などのミスを防ぐためにもCayenneの設定は変更したくない。
本家のガイドでは、これを実現する方法として
$ mvn test -DcayenneTestConnection=conn1
というオプションの説明がされています。
ところがこれが上手くいかず、あれこれ悩んだ結果、別の方法でやってみることにしました。
"cayenneTestConnection"を使えるようにするには
ガイドのページには、
Cayenne provides a comprehensive suite of unit tests. To execute unit tests you must first get Cayenne from SVN, install JDK 1.5 and obtain the latest Maven.
Apache Cayenne » Running Unit Tests
と書かれています。Mavenリポジトリ検索やSVNなどを見てざっと調べたところでは、どうやらこの機能は"cayenne-jdk1.5-unpublished"という非リリース?のアーティファクトに含まれる機能のようです。
さすがに面倒すぎるので、コア機能になることを期待しつつ、この方法はパス。
方法その1:テストケースに直接切り替え処理を書く
公式のWikiに書いてある方法です。
まずは説明のとおり、$HOME/.cayenne/connection.propertiesに
postgres.cayenne.adapter = org.apache.cayenne.dba.postgres.PostgresAdapter postgres.jdbc.driver = org.postgresql.Driver postgres.jdbc.url = jdbc:postgresql://localhost:5432:mydb postgres.jdbc.username = username postgres.jdbc.password = password
と記述します。
次にBasePageTestを作ります。スーパークラスの@BeforeClassで呼び出すことで、テストの最初に呼ばれることになります(...なるはず)。各ページのテストケースはこれを継承すれば、WicketTesterの初期化も一ヶ所でできて一石二鳥です。
import java.sql.*; import org.apache.cayenne.conf.*; import org.apache.cayenne.conn.*; import org.apache.wicket.util.tester.*; import org.junit.*; public class BasePageTest { protected WicketTester tester; @BeforeClass public static void initializeDataSource() throws SQLException { ConnectionProperties connprop = ConnectionProperties.getInstance(); DataSourceInfo dsinfo = connprop.getConnectionInfo("postgres"); DriverDataSource ds = new DriverDataSource(dsinfo.getJdbcDriver(), dsinfo.getDataSourceUrl(), dsinfo.getUserName(), dsinfo.getPassword()); // ↓これが無いとConfiguration.getSharedConfiguration()でエラーになる Configuration.initializeSharedConfiguration(new DefaultConfiguration() { { setIgnoringLoadFailures(true); } }); Configuration.getSharedConfiguration().getDomain().getNode("Node1").setDataSource(ds); } @Before public void setUp() throws Exception { tester = new WicketTester(new WicketApplication()); } }
"setIgnoringLoadFailures(true)"の箇所は、Configuration.getSharedConfiguration()を実行したときにJNDI参照できないとエラーになってしまいますので、それを無視して処理を続行するための仕掛けです。
実はこれが一番苦労したところです。
modelerのpreference-"Local DataSources"の設定を使えたら良いのにと思ってちょっとだけ調べたら、コア(cayenne-server)の機能にmodelerの機能が依存してしまうことになるので簡単じゃなさそうです。
方法その2:簡易JNDIサーバを立てる
「JNDIサーバが無いなら作ればいいじゃない」という方法です。
JUnitテストで使う即席のJNDIデータソースを用意するを参照してください。
ちょっとてこずりましたが、副産物が色々とあったのでやってみた甲斐はありました。