Seasar(シーサー)は、国内のコミュニティ「The Seasar Project」によって開発が行われているオープンソースプロダクトだ。DI+AOPコンテナとして評価が高いSeasarV2は、J2EE開発の現場にも影響力を持ち始めた。例えば電通国際情報サービスがSeasar Projectを正式に支援することを表明し、2005年6月からは同社による商用サポートサービスが開始されている。本連載では、同プロジェクトの代表的なプロダクトを紹介していく。(編集局)
SeasarV2(以下、S2)には、テストツールJUnit(http://junit.org/)を拡張したテストフレームワークが用意されています。これは「S2Unit」と名付けられています。JUnitを用いる場合はjunit.framework.TestCaseクラスを継承してテストプログラムを作成しますが、S2Unitの場合は、これのサブクラスであるorg.seasar.extension.unit.S2TestCaseクラスを継承してテストプログラムを作成します。
S2でテストを行う利点は、アプリケーションサーバなど、S2以外の実行環境を用意しなくてもよいということでしょう。もちろんアプリケーションによってはJDBCドライバなどが必要になることはありますが、例えばEJBのようにアプリケーションサーバにデプロイするといった手続きは必要ありません。S2でのテストはテスト用のdiconファイルを用意するだけで済みます。そしてこの後すぐ紹介するように、テスト用のdiconファイルでアスペクトの機構を用いてモックオブジェクトを設定することができますので、テスト用のオブジェクトを特別に作成する必要がありません。また、データベースにアクセスするアプリケーションの場合でも、第3回で紹介したDataSetをデータベースに見立ててテストを行うことができるようになっています。
以下にS2UnitにおけるJUnitから拡張した機能の一部を示します。詳細はSeasarプロジェクトのドキュメント(http://www.seasar.org/S2Unit.html)をご覧ください。
S2には、MockInterceptorという、本来のオブジェクトをテスト用のモックとして扱うためのインターセプタが用意されています。これを用いたテストを行う方法を紹介しましょう。ここでは、第2回「DI+AOPを実現するSeasar V2」で登場した面積を求めるアプリケーションのモックをこのインターセプタを使ってテストしてみます。なお、今回に関連するソースコードはここからダウンロードできます。
テストしたいアプリケーションに、その基となるインターフェイスが存在している場合は、そのインターフェイスさえあれば、S2がそれをモックオブジェクトにしてくれます。具体的には、diconファイルのコンポーネント定義の<aspect>〜</aspect>間でMockInterceptorのコンポーネント定義を書き込むだけです。
モックオブジェクトを定義するのは、MockInterceptorのsetReturnValueメソッドで、どのメソッドからどの値を返すかをdiconファイルに直接記述します。テストするメソッドが複数存在する場合は、setReturnValueメソッドによる設定を複数記述してください。
モックオブジェクトを作成する例<!-- このインターフェイスを持つモックオブジェクトを定義する --> |
このようにして定義したモックオブジェクトを用いてテストを行う例をリスト1、実行結果をその下に示します。テストはS2Unitのフレームワークにより自動的に行われますので、その流れを説明します。
リスト1 第2回「リスト1」のモックオブジェクトをテストする [AreaTest.java] |
package myfirst.test; |
|
次に、データベースにアクセスするアプリケーションのテストをどのように行えばよいかを紹介します。この場合は、まずアプリケーションの実行後に予想されるデータベースの状態をあらかじめDataSetオブジェクトとして作成しておき、それと実際の結果とを比較します。
このとき用いるDataSetオブジェクトはテストプログラムの中で直接データを設定しても良いですし、Excelファイルからインポートすることもできます。そうすれば、直接データベースを使用せずにデータベースへのアクセスのテストが可能になります。ここではDataSetオブジェクトに登録するデータを直接生成し、プログラムの実行結果と比較する方法を紹介します。
まず、ここで使用するDataSetオブジェクトを生成してみます。生成するオブジェクトは、以下に示すcategoryテーブルと同じデータを持つDataTableオブジェクトです。このオブジェクトをDataSetに登録すると、DataSetをテスト用のデータベースとして扱うことができます。MySQLのデータベースに登録されているcategoryテーブルのデータと、これに準じたデータをDataSetオブジェクトに登録する例を以下に示します。
id | name |
---|---|
1 | 食費 |
2 | 交通費 |
3 | 書籍代 |
4 | 光熱費 |
5 | 家賃 |
6 | 給料 |
categoryテーブルのデータを生成し、DataSetに登録する例 |
public DataSet initDataSet() throws Exception { |
まず、このDataSetオブジェクトの内容と、画面1のようなExcelファイルから読み込んだデータの内容とを比較してみます。読み込むために必要なデータの内容についてはSeasarプロジェクトのドキュメント(http://www.seasar.org/testtech.html#s2unitexcel)を参照してください。
Excelファイルからデータを読み込むには、以下のように、S2TestCaseクラスのreadXlsメソッドを用います。このメソッドを実行するとDataSetを取得することができます。というのは、Excelファイルに複数のシートが作成されていると、そこから複数のDataTableオブジェクトを生成してDataSetオブジェクトに登録するためです。
DataSet
fromXls = readXls( "Excelファイル名" ); |
両者のデータを比較するためには、DataSetを引数とするassertEqualsメソッドかDataTableを引数とする同メソッドを用いることができます。ここで用いるassertEqualsメソッドは、JUnitのそれとは異なり、S2Unitで新たに実装(拡張)されたものです。Excelファイルにcategoryテーブルのデータしか作成されていない場合はDataSetを引数にして比較させることができますが、Excelファイルに別のテーブルのデータも作成されている場合は、DataSetから個別のDataTableを取得して比較しなければなりません。
DataSet同士を比較する場合 assertEquals(
fromXls, s2Test ); |
assertEquals(
fromXls.getTable( "category" ), s2Test.getTable( "category"
) ); |
今度は、第3回の「MapListによるデータの取得」の項で紹介したMapListResultSetHandlerを用いて取得した結果との比較をしてみます。この場合は、まずこのコンポーネントを持つSelectHandlerオブジェクトをDIコンテナから取得しなくてはなりません。ここではS2TestCaseインスタンスが保持しているものをgetContainerメソッドにより取得しておいてから、目的とするSelectHandlerを取得します。
DataSetオブジェクトのデータとSelectHandlerから取得したデータを比較するには、以下のように、assertMapListEqualsメソッドの第2引数、第3引数にそれぞれを設定し、実行します。MapListからDataSetへ、またはその逆への変換は必要ありません。
SelectHandler handler = (SelectHandler)getContainer() |
さらに、このDataSetオブジェクトのデータとSQL文の実行結果を比較してみます。SQL文の実行結果はDataTableオブジェクトで取得するため、両者の比較には、DataTableを引数とするassertEqualsメソッドを用います。
比較の対象とするSQL文の実行結果を取得するには、以下のように、S2TestCaseクラスのreadDbBySqlメソッドを実行します。第1引数がSQL文(SELECT)で第2引数がDataTableオブジェクトに付けるテーブル名です。
DataTable
category = |
最後に、先ほどデータを登録したDataSetと比較します。両者の内容が同じであれば、このテストは正常に終了します。
assertEquals(
category, s2Test.getTable( "category" ) ); |
S2TestCaseには、これまで紹介した以外にも、例えばテーブル名からDataTableオブジェクトを生成するreadDbByTableメソッドやDataSetの内容をそのままデータベースに書き込むwriteDbメソッドなどのように便利なメソッドがいろいろと用意されていますので、興味がある方はソースコードを読んだり、APIドキュメントを生成したりして探してみてください。
今回までで、Seasarプロジェクトの中核であるSeasarV2(S2)が持つ機能について、その一部を紹介してきました。DIコンテナ、AOP、DBアクセス、ユニットテストというように、S2だけでもさまざまな機能が用意されていることがお分かりいただけたでしょうか。もっと詳しく知りたいという方は、Seasarプロジェクトのドキュメントや、開発者のWebサイトなどをお読みいただき、さらに理解を深めていただければと思います。
次回はO/RマッピングによるDBアクセスを行うS2Daoについて紹介していきます。引き続きどうぞよろしくお願いいたします。
Copyright © ITmedia, Inc. All Rights Reserved.