Spring+JUnit+DbUnitではまる。。。
久しぶりにDbUnitを使おうとおもったらはまりまくった。
環境はeclipse3.4.1上のプロジェクト(古いけどこのときのシステムはこれで統一してたので。。。)
Springは2.5.6
- 1つ目のはまりはコンパイルエラー
まずアノテーション@RunWith(SpringJUnit4ClassRunner.class)を追加すると、
型 org.junit.internal.runners.JUnit4ClassRunner を解決できません。 必要な .class ファイルから間接的に参照されています
のエラーメッセージ。。。
Springにはいっていたjunit-4.4.jarをクラスパスに追加して解決。
- 2つ目のはまりトランザクション
初期データをDataSetからCLEAN_INSERTを行っても、テスト実行時は別のトランザクションになってしまいテストができなかった。。。
データソースをとってくるところをorg.springframework.jdbc.datasource.TransactionAwareDataSourceProxy
に変更。
元のDBCPのところはidをdbcpDataSourceにして以下を追加
<bean id="dataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy"> <constructor-arg ref="dbcpDataSource" /> </bean>
これで解決。
- 3つ目のはまり実行時例外
さてテストを実行しようとしたら
java.lang.SecurityException: class "org.junit.internal.runners.JUnit4ClassRunner"'s signer information does not match signer information of other classes in the same package
はぅ。。。
ライブラリが競合してたみたい。。。
junit-4.4.jarの順序を変更したら動くようになった。
さて、テストがんばりましょか。
とりあえず、動いたソースをアップ
内容は初期データを取り込んだテーブルをSELECTで取り出し
結果をExcelで比較する。
BeanのリストをIDataSetにするのは、
http://sourceforge.jp/projects/dbunitng/
を使わせていただきました。
import java.io.BufferedInputStream; import java.net.URL; import java.util.List; import javax.annotation.Resource; import javax.sql.DataSource; import org.apache.log4j.xml.DOMConfigurator; import org.dbunit.Assertion; import org.dbunit.DataSourceDatabaseTester; import org.dbunit.IDatabaseTester; import org.dbunit.dataset.IDataSet; import org.dbunit.dataset.excel.XlsDataSet; import org.dbunitng.dataset.BeanListConverter; import org.junit.After; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.transaction.TransactionConfiguration; import org.springframework.transaction.annotation.Transactional; @RunWith(SpringJUnit4ClassRunner.class) @Transactional @TransactionConfiguration(defaultRollback = true) @ContextConfiguration(locations = "/resources/spring/batchApplicationContext.xml") public class DbUnitTest { private static final String LOG4J_CONFIG_FILE = "src/main/resources/log4j/log4j.xml"; private IDatabaseTester tester; @Autowired private DbUnitDao dbUnitDao; @Resource private DataSource dataSource; @BeforeClass public static void setUpBeforeClass() throws Exception { DOMConfigurator.configure(LOG4J_CONFIG_FILE); } @Before public void setUp() throws Exception { tester = new DataSourceDatabaseTester(dataSource); tester.setDataSet(getDataSet()); tester.onSetup(); } @After public void after() throws Exception { tester.onTearDown(); } protected IDataSet getDataSet() throws Exception { URL url = DbUnitTest.class.getResource("import-data.xls"); BufferedInputStream is = new BufferedInputStream(url.openStream()); XlsDataSet dataset = new XlsDataSet(is); return dataset; } @Test public void hogehoge() throws Exception { List<DbUnitBean> list = dbUnitDao.queryAll(); BeanListConverter converter = new BeanListConverter(list); IDataSet dataSet = converter.convert(); URL url = DbUnitTest.class.getResource("expected-data.xls"); BufferedInputStream is = new BufferedInputStream(url.openStream()); XlsDataSet expected = new XlsDataSet(is); Assertion.assertEquals(expected, dataSet); } }
STS2.3.3M2 リポジトリが足りない。
Pluginのリポジトリに以下を追加しないとaspectjtoolsが入らない
<pluginRepositories> <pluginRepository> <id>spring-maven-release</id> <name>Spring Maven Release Repository</name> <url>http://maven.springframework.org/release</url> </pluginRepository> <pluginRepository> <id>spring-maven-milestone</id> <name>Spring Maven Milestone Repository</name> <url>http://maven.springframework.org/milestone</url> </pluginRepository> <pluginRepository> <id>spring-roo-repository</id> <name>Spring Roo Repository</name> <url>http://spring-roo-repository.springsource.org/release</url> </pluginRepository> </pluginRepositories>
ここを追加しないとhibernate-jpa-2.0-apiなどhibernateまわりのjarファイルがダウンロードされない。
<repository> <id>JBOSS</id> <name>JBoss Repository</name> <url>http://repository.jboss.org/maven2/</url> </repository>
今のところ気付いたのはこれだけ。
Spring Roo 1.0リリース
今後の展開が気になるのでメモです。
Spring Roo プロジェクトページ
Spring Roo 1.0M1 リリース
2010/07/18 追記
日本語訳発見♪
http://www.spring-roo.com/home
DataAccessExceptionのマッピング変更
Springを利用したDBへのアクセスでSQLExceptionはDataAccessExceptionの継承クラスに変換されます。
この変換には「sql-error-codes.xml」で定義された情報で、変換されるクラスが決定される。
このXMLファイルは、springのjarファイル内の「org.springframework.jdbc.suport」に存在しており、自分用にカスタマイズしたい場合は、このファイルを編集して、クラスパスの通っているディレクトリの直下に配置することでオーバーライドすることが可能となっている。
さらに自分で作成したDataAccessExceptionの継承クラスに変換したい場合は、以下のように定義します。
ここで定義できるのは、DataAccessExceptionの継承クラスしか定義できません。
#PostgreSQLをサンプルに
<bean id="PostgreSQL" class="org.springframework.jdbc.support.SQLErrorCodes"> <property name="useSqlStateForTranslation"> <value>true</value> </property> <property name="badSqlGrammarCodes"> <value>03000,42000,42601,42602,42622,42804,42P01</value> </property> <property name="dataAccessResourceFailureCodes"> <value>53000,53100,53200,53300</value> </property> <property name="dataIntegrityViolationCodes"> <value>23000,23502,23514</value> </property> <property name="cannotAcquireLockCodes"> <value>55P03</value> </property> <property name="cannotSerializeTransactionCodes"> <value>40001</value> </property> <property name="deadlockLoserCodes"> <value>40P01</value> </property> <property name="customTranslations"> <list> <!-- ここから -- > <bean class="org.springframework.jdbc.support.CustomSQLErrorCodesTranslation"> <!-- 対応するSQL例外のエラーコード --> <property name="errorCodes" value="23503" /> <!-- 変換する例外クラス --> <property name="exceptionClass" value="jdbc.ForeignKeyException" /> </bean> <bean class="org.springframework.jdbc.support.CustomSQLErrorCodesTranslation"> <property name="errorCodes" value="23505" /> <property name="exceptionClass" value="jdbc.DuplicateKeyException" /> </bean> <!-- ここまで --> </list> </property> </bean>
※Springframework2.5.4で確認しました。
XPのディスクにアクセスできない
友達からの頼まれごとでVistaにXPがインストールされているHDDの情報を抜き出す作業をしました。
XPが入っているほうはHDDしかなかったので、HDDケースに入れてUSBでVistaマシンにつないで中身が見れるの確認できたのですが、ユーザのホームディレクトリを見ようとするとアクセス権がないと言われてアクセスできない。。。
お気に入りやマイドキュメントの中身を移行したいのに・・・
少し調べてみるとVistaには「パスワード保護共有」というのがあり、このせいでアクセスできない様子。
「コントロールパネル」−「ネットワークと共有センター」を開き、「パスワード保護共有」の設定を無効に設定。
これでアクセスできるようになりました。(少し焦ったけど・・・)
SSLアクセラレータ利用時のリダイレクト
HttpServletResponse#sendRedirect(java.lang.String location)を使ってリダイレクトを行った場合に、引数に渡される「location」が相対URLの場合は絶対URLが構築されます。
例)
「http://host.domain/context/hoge.jsp」 にアクセスした際に、この処理の中で
「/foo.jsp」を引数に渡してリダイレクトを行うと、クライアントには
「http://host.domain/context/foo.jsp」として渡されます。
通常はこれで問題ないのですが、SSLアクセラレータを利用した場合は、
クライアントのアクセスしたURL:「https://host.domain/context/hoge.jsp」
tomcatが受け付けたURL:「http://host.domain/context/hoge.jsp」
となり「https」が「http」となってしまいます。
このためリダイレクトの絶対URLが構築された際に「http」として構築されてしまいます。
この問題を回避するにはserver.xmlのconnectorタグの属性を変更すれば回避できます。
proxyName="サーバ名"
proxyPort="ポート番号" ※通常SSLなら443
scheme="スキーマ" ※通常SSLならhttps
secure="true" これは設定しなくてもよいけど、request.isSecure()の戻り値がtrueになる。