#freeze [[FrontPage]] 2008/01/15からのアクセス回数 &counter; #contents * Spring-MVCプラグイン機能追加(テストケース) [#a8a163c0] Spring-MVC用archeTypeプラグインには、単体テスト用のひな形が含まれていなかったので 1.1.0版でテストケースを取り込みました。 ** Spring-MVCプラグイン1.1.0のインストール [#b55bf04e] Spring-MVCプラグインの1.1.0のインストールには以下の4ファイルが必要です。 - archeTypeプラグインjarファイル #ref(spring-mvc-archetype-1.1.0.jar); - archeTypeプラグインpomファイル #ref(spring-mvc-archetype-1.1.0.pom); - GenMVCプラグインjarファイル #ref(maven-GenMVC-plugin-1.1.0.jar); - GenMVCプラグインpomファイル #ref(maven-GenMVC-plugin-1.1.0.pom); 上記の添付ファイルをダウンロードしてください。近々公開用リポジトリを用意する予定です(それまでinstall-fileをご使用ください)。 - 次に以下のコマンドを実行してください。 #pre{{ mvn install:install-file \ -Dfile=./spring-mvc-archetype-1.1.0.jar \ -DgroupId=jp.co.pwv.spring-mvc-archetype \ -DartifactId=spring-mvc-archetype \ -Dversion=1.1.0 \ -DpomFile=./spring-mvc-archetype-1.1.0.pom \ -Dpackaging=jar mvn install:install-file \ -Dfile=./maven-GenMVC-plugin-1.1.0.jar \ -DgroupId=org.apache.maven.plugins \ -DartifactId=maven-GenMVC-plugin \ -Dversion=1.1.0 \ -DpomFile=./maven-GenMVC-plugin-1.1.0.pom \ -Dpackaging=jar }} ** テストケースで追加されたファイル [#vf21bddd] テストケースで追加されたファイルは以下の通りです。 #ref(fileTree.jpg); - test/java/example/test/TestCase.java JUnit用のjavaクラスファイルです。 - test/resources/WEB-INF/applicationContext.xml - test/resources/WEB-INF/custom-editor.xml - test/resources/WEB-INF/servlet-def.xml - test/resources/WEB-INF/servlet-stub.xml - test/resources/WEB-INF/hbm-dir/Member.hbm.xml これらは、main/webapp/WEB-INFのファイルと同じものを使用します。 ''特にapplicationContext.xml, servlet-stub.xmlはGenMVCプラグインを実行すると 変更されますので、test/resourcesへのコピーが必要です。'' - test/resources/WEB-INF/db-def.xml(変更あり) JUnit用に以下の定義を追加しました。 #pre{{ <!-- TransactionManager --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <!-- DbUnitHelperDao --> <bean id="dbUnitHelperDao" class="jp.co.pwv.utils.DbUnitHelperDao"> <property name="sessionFactory" ref="sessionFactory" /> </bean> }} transactionManagerは、AbstractTransactionalSpringContextTestsが必要とし、 dbUnitHelperDaoは、DbUnitHelperDaoが必要とします。 DbUnitHelperDaoは、テストデータのdump, resotoreとprintメソッドを提供します。 GenMVCプラグインで新たにManagerクラスを追加した場合には、TestCase.javaの35行 #pre{{ dbUnitHelperDao.addHelper(memberManager.getHelper()); }} addHelperでManagerクラスのhelperを追加登録してください。 - test/resources/WEB-INF/jdbc.properties.xml(変更あり) 単体テストでは、デバッグ時にデータベースの状態を確認する必要がありますので、 HSQLDBのサーバ機能を使用するように変更しました。 #pre{{ # サーバとして使用する場合 db.url=jdbc:hsqldb:hsql://localhost }} HSQLDBのインストールは、http://www.pwv.co.jp/take_public_html/DevTool/DevTool_c8.html#doc1_498 を参照してください。 - test/resources/dump.xml(新規追加) DBUnitのFlatXmlDataSet形式のテストデータ記述ファイルです。 dump.xmlの内容は、 #pre{{ <?xml version="1.0" encoding="Windows-31J"?> <dataset> <T_MEMBER address='Nakano-ku' id='1' name='Hiroshi TAKEMOTO'/> </dataset> }} のようなテーブル名をタグとし、フィールド名を属性とするXMLファイルです。 - test/resources/testdata-def.xml(新規追加) 単体テストでは、検証用のデータをプログラムで用意する必要があります。これをjavaで記述すると 非常に面倒なので、Springの機能を使って検証用テストデータを作成するために用意しました。 #pre{{ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"> <beans> <bean id="expectedMember" class="example.test.domain.Member"> <property name="id" value="1" /> <property name="name" value="Hiroshi TAKEMOTO" /> <property name="address" value="Nakano-ku" /> </bean> </beans> }} ** ひな形の作成 [#kb6a3c0e] 最初のバージョンと変更となるはarchetypeVersionだけです。 例題は、 #pre{{ mvn archetype:create \ -DgroupId=example.test \ -DartifactId=test \ -DarchetypeArtifactId=spring-mvc-archetype \ -DarchetypeGroupId=jp.co.pwv.spring-mvc-archetype \ -DarchetypeVersion=1.1.0 }} となります。 ** 単体テストの実行 [#f392e208] - HSqlDBのサーバ HSqlDBのサーバを起動します。HSqlDBをインストールしたディレクトリをHSQLDB_HOMEとすると #pre{{ cd $HSQLDB_HOME/demo ./runServer.sh }} Windowsの場合には、runServer.batを使用してください。 - mvnでのテスト 次にmvnで単体テストを実行します。 #pre{{ mvn test }} と #pre{{ [INFO] Scanning for projects... [INFO] ------------------------------------------------------------------------ .... ------------------------------------------------------- T E S T S ------------------------------------------------------- Running example.test.TestCase .... MEMBER: ADDRESS='Nakano-ku' ID=1 NAME='Hiroshi TAKEMOTO' Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.953 sec Results : Tests run: 3, Failures: 0, Errors: 0, Skipped: 0 .... }} のように出力され、Tests run: 3で、3つのテストケースを実行し、エラーが無かったことが 分かります。 ** テストケースについて [#xbf14bcf] *** 設定の前準備 [#u49ec2c0] - TestCaseの選択 データベースを扱っているため、テストの影響がないようにAbstractTrasactionalSpringContextTestsを継承しています。 - Spring設定ファイル Springの設定ファイルは、getConfigLocationsメソッドで返すようにします。 #pre{{ public String[] getConfigLocations() { return new String[] { "WEB-INF/applicationContext.xml", "WEB-INF/custom-editor.xml", "WEB-INF/db-def.xml", "WEB-INF/servlet-def.xml", "WEB-INF/servlet-stub.xml", "testdata-def.xml" }; } }} - 各テストでの開始と終了の処理 各テストでの開始の処理をonSetUpInTransactionで、終了の処理をonTearDownInTransactionで定義することができます。ひな形では、MemberManager, dbUnitHelperをApplicationContextから取得し、dbUnitHelperにmemberManagerのhelperを登録しています。 #pre{{ public void onSetUpInTransaction() throws Exception { super.onSetUpInTransaction(); memberManager = (MemberManager)getApplicationContext().getBean("memberManager"); dbUnitHelperDao = (DbUnitHelperDao)getApplicationContext().getBean("dbUnitHelperDao"); dbUnitHelperDao.addHelper(memberManager.getHelper()); } public void onTearDownInTransaction() throws Exception { super.onTearDownInTransaction(); } }} *** memberManager(Daoのテスト) [#de284dd9] Daoのテストの例をtestFindByIdメソッドに示します。 - dbUnitHelperDaoのresotreメソッドでデータベースにテストデータをセットします - DaoのfindByIdメソッドでmemberを取得します。 - assertEqualsで値の確認をします。 通常はこのようにしますが、helperのprintメソッド使う方法も例としてあげています。 testFindByIdメソッドは、以下の通りです。 #pre{{ public void testFindById() { dbUnitHelperDao.restore("src/test/resources/dump.xml"); Member member = memberManager.findById(new Integer(1)); assertEquals("Hiroshi TAKEMOTO", member.getName()); assertEquals("Nakano-ku", member.getAddress()); // or you can check using IMember.print method. Member expectedMember = (Member)getApplicationContext().getBean("expectedMember"); System.out.println(memberManager.print(member)); assertEquals(memberManager.print(expectedMember), memberManager.print(member)); } }} *** EditMemberController(コントローラのテスト) [#xcde89d9] EditMemberControllerのテストには、MockHttpServletRequestを使います。 - 第1引数でPOSTまたはGETを指定し、第2引数にURLを指定します - addParameterメソッドでパラメータを追加します - editMemberControllerをApplicationContextから取得し、handleRequestメソッドを呼び出します - handleRequestの戻り値としてModelAndViewが返されます - ModelAndViewからビューの名前とモデルからmemberの値を確認します testEditMemberControllerは、以下の通りです。 #pre{{ public void testEditMemberController() { dbUnitHelperDao.restore("src/test/resources/dump.xml"); MockHttpServletRequest req = new MockHttpServletRequest("POST","editMember.htm"); req.addParameter("id","1"); EditMemberController editMemberController = (EditMemberController)getApplicationContext().getBean("editMemberController"); ModelAndView mv = null; try { mv = editMemberController.handleRequest(req,new MockHttpServletResponse()); } catch (Exception err) { err.printStackTrace(); } Member expectedMember = (Member)getApplicationContext().getBean("expectedMember"); assertEquals("redirect:memberops/list.htm", mv.getViewName()); Member member = (Member)mv.getModel().get("member"); assertEquals(memberManager.print(expectedMember), memberManager.print(member)); } }} ** 簡単単体テスト [#z25f1e26] 単体テストを記述することは最初は億劫ですが、一度ひな形ができるとそのパターンをコピー・ペーストすれば 他のテストが簡単にできるので、テストケースのひな形を使って単体テストに挑戦してみてください。 ** コメント [#gcda2a35] この記事は、 #vote(おもしろかった[3],そうでもない[2],わかりずらい[0]) #vote(おもしろかった[3],そうでもない[2],わかりずらい[1]) 皆様のご意見、ご希望をお待ちしております。 #comment_kcaptcha