Suite)の環境作成と簡単なWebアプリの作成]Java、Eclipse、JUnitに関連した技術情報のブログです。ユニットテストスポンサードリンクStruts1ももう過去の遺物になり、SAStrutsもEOLとなりもう半年以上が経過しました。言え、すぐにSAStrutsから脱却できるわけでもなく・・・そのような製品が多いと思います。Springの2択だとも思います。前置きが長くなりましたが、今回からSpringのエントリーを書かせていただこうと思います。当然ですが、自動テストの比重が大きい内容にしていきます。Suite)の環境構築と簡単なWebアプリとなります。Bootは利用いたいません。内容は以下の通りです。Suite)環境の構築STSのダウンロードhttp://spring.io/tools/sts/allにアクセスして以下の画像の赤枠部分のご利用の環境のリンクをクリックします。64ビットをクリックしてダウンロードします。(どうでもいい話ですがMacの場合は64ビットだけです。)ダウンロードが完了したら適当な場所に解凍してください。解凍で生成されたフォルダのstsをクリックすれば起動します。起動時の画像は以下のようになります。PackプラグインのインストールビルドツールはMavenではなくGradleを利用します。Mavenの方がメジャーですがGradleの方が色々できて生産性に寄与すると言えます。marketplaceを起動してgradeで検索します。Pack」プラグインをインストールします。STSと言ってもEclipseをベースに開発されていますので、プラグインのインストールはEclipseと全く同じです。Pack」プラグインが利用可能となります。画面を表示するだけの画面の作成とテストの実装プロジェクトの作成パッケージエクスプローラで右クリックメニューを表示し[New]-[Other...]をクリックします。Project]を選択し「Next」ボタンをクリックします。QuickStart」を選択し「Finish」をクリックします。Gradleですので、必要なライブラリのダウンロードが必要となり処理には少々時間を要します。終了するとパッケージエクスプローラにSpringMvcSampleが表示されます。自動で生成されたorg.gradleパッケージは利用しないため削除しておきます。Frameworkは5.0を利用します。8以上が必須になっています。6と7が利用できるのですが、4.3は2019年までサポートが切れることが予告されていますので、今後の開発では5.0以降を利用するべきです。プロジェクト直下のbuild.gradleを以下のように変更します。'repos'}}}変更内容はコメントに記載しているとおりですがidkのバージョンは1.8でspring-webmvcの依存関係を追加しているだけとなります。Server」で実行できませんが、その部分については後述させていただきます。記載内容を反映します。Dependencies]をクリックします。Compilerを1.8に変更し「OK」ボタンをクリックします。以上で基本的な環境設定は完了となります。World!を実装します。Controllerにリクエストを行うとHTMLが返却される例となります。web.xmlの作成まずはSpringがリクエストを処理するための設定を行うweb.xmlの作成を行います。src/main/webapp/WEB-INFにweb.xmlファイルを作成し、内容を以下のようにしてください。--><jsp-config><jsp-property-group><url-pattern>*.jsp</url-pattern><el-ignored>false</el-ignored><page-encoding>UTF-8</page-encoding><scripting-invalid>false</scripting-invalid></jsp-property-group></jsp-config></web-app>ApplicaiotnContextが利用する設定ファイルの作成SpringのApplicaiotnContextが利用する設定ファイルを作成します。これはweb.xmlでclasspath:/META-INF/spring/contextConfigLocation.xmlと指定したファイルとなります。Springでは本設定はJavaクラスでも行えるのですが、今回は一番オーソドックスなxmlで作成します。src/main/resources配下にMETA-INF/spring/contextConfigLocation.xmlを作成します。ファイルの中身は以下のようになります。/></bean></beans>こちらもコメントに記載しているとおりですが、コンポーネントスキャン対象のパッケージとviweの定義がポイントとなります。Controllerの作成HelloWorldControllerを以下の内容で作成します。"index";}}・6行目SpringのDIコンテナにHelloWorldControllerをコントローラとして認識してもらうためのアノテーションを付与しています。コントローラはStrutsのActionに相当します。DIコンテナにに登録するクラスの指定には@Component、@Service、@Repository、@Controllerが指定可能です。詳細につきましては次回以降で説明させていただきます。・7行目アプリケーションコンテキストのルートパスがHelloWorldControllerにマッピングされるように指定しています。@RequestMappingはコントローラクラスとそのメソッドに指定可能となります。・9行目helloWorldメソッドにはGETで有効とのアノテーションを付与しています。クラスとメソッドに指定された@RequestMappingによって、アプリケーションコンテキストのルートパスへのGET命令がhelloWorldメソッドにマッピングされます。文字列”index”を返却しています。この文字列によってコンテーキスルートのindex.jspが描画されます。contextConfigLocation.xmlでJSPの格納場所は/WEB-INF/views/jsp/に設定しているので/WEB-INF/views/jsp/index.jspが実際に対応するファイルとなります。jspの作成src/main/webapp/WEB-INF/views/jsp配下にindex.jspを作成します。内容は以下のとおりです。Server」に配備できませんのでwtpプロジェクトに変換します。build.gradleの3行目に以下の記載を追記します。Launcher]をクリックします。表示されたダイアログでeclipseと入力リターンボタンを押下します。実行が成功すると以下のようなログが出力されます。Dependencies]をクリックします。Server」で実行してみます。Server]をクリックします。以下の画面が表示されるので「Next」をクリックします。SpringMvcSampleがConfiguredの一覧に表示されていることを確認してます。Configuredの一覧に表示されていない場合は、Availableの一覧に表示されているSpringMvcSampleを選択し「Add」ボタンをクリックし「Finish」をクリックします。Eclipseの組み込みブラウザでコンテキストルートが表示さました。表示内容も想定どうりです。ユニットテストの実装これではイマイチちゃんと動作しているか不明確なのでテストを実装してみます。Springはテストが効率的に行える仕組みが提供されています。Webアプリも当然対象です。SAStrutsもテストを実装できるのですが、モックはEasyMockですし、テストを考慮したDI設定なども結構煩雑ですよね。書きつつ、昔は私もStrutsとEasyMockでテスト実装していたので時代が違うだけなのかとも思います。依存関係の追加まずは必要な依存関係の追加を行います。spring-testとmockitoを追加します。build.gradleのdependencies以下のようになりました。Dependencies]をクリックします。テストの実装と実行HelloWorldControllerTestをsrc/test/javaに作成します。内容は以下のとおりです。{//コンテキストルートにgetでアクセスしOKのスタータスと"index"が返却されることを確認mockMvc.perform(get("/")).andExpect(status().isOk()).andExpect(view().name("index"));}}ポイントとしは@ContextConfiguration(locationsでspringの設定ファイルの指定を指定している部分とWebApplicationContextを@Autowiredを付与して宣言し、springによってインジェクションされた@Autowiredを利用してMockMvcを生成しテストに利用するところです。簡単にテストが実装できるようによく考えられていますよね!早速実行してみます。as]-[JUnit-Test]をクリックします。入力項目を有する画面の作成とテストの実装(第一弾)シンプルなログイン画面風のものを作成します。最終的には入力画面にありがちな入力チェックとログイン成功時の画面遷移まで実装するのですが第一弾としては入力部分と分岐のない画面遷移だけとなります。LoginFormの作成LoginFormを作成します。ログイン画面ですのでloginNameとloginPasswordを保持するPOJOとなります。loginPassword;}}LoginControllerの作成/login/indexにアクセスするとログイン画面を表示ログインが成功したらlogin/successに遷移ログインが失敗したらlogin/indexに遷移するコントローラを作成します。"login/success";}}ポイントと言うほどではないですが、LoginControllerの@RequestMappingには”/login”を指定しておりindexメソッドでは”index”、loginでは”login”を指定することで/login/indexはindexメソッドにマッピング/login/loginはloginメソッドにマッピングとなります。index.jpsの作成src/main/webapp/WEB-INF/views/jsp/loginにindex.jspを作成します。index.jspの内容は以下のとおりです。value="ログイン"></div></form:form></body></html>テストの実装ほぼ中身がない状態ですので、ブラウザで確認する方が早いのですがテストを実装してみます。基本的な部分はHelloWorldControllerTestと同様です。/login/indexにアクセスした時のテストを含んだLoginControllerTestは以下のようになります。/login/indexにgetでアクセスしOKのスタータスと"login/index"が返却されることを確認mockMvc.perform(get("/login/index")).andExpect(status().isOk()).andExpect(view().name("login/index"));}}ここではHelloWorldControllerTestとほぼ同じで、パスが異なるだけです。/login/loginのテストを追加してみます。org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;を追加する必要があります。“loginPassword”)でloginFormのloginPasswordに”password”がセットされて、このloginFormがHelloWorldController.loginの引数として渡されます。この部分の確認用の検証項目を追加すると以下のようになります。(import文の説明を記載すると無駄に説明が長くなりますので省略させていただきます。クラス全体は最後に記載させていただいていますので、そちらを参照ください。is(loginForm.getLoginPassword()));}「第一弾」としてはこれで完成です。入力項目を有する画面の作成とテストの実装(第二弾)入力チェック部分を実装してみます。言っても、LoginFormにアノテーションを追加するだけです。hibernate-validatorの依存関係の追加SpringではFormのバリデーションにhibernate-validatorを利用していますのでbuild.gradleにhibernate-validatorとvalidation-apiの依存関係を追加します。'1.10.19'}LoginFormへバリデーション用のアノテーションを追加LoginFormは以下のようになります。loginPassword;}}loginNameはNotEmptyloginPasswordはNotEmptyかつ10文字以上16文字以下かつ英数字で構成とのチェックが行われるように指定しています。LoginControllerへバリデーション用のアノテーションを追加コントローラでは、LoginFormのバリデーションを有効にするためのアノテーションを付与する必要があります。具体的にはloginメソッドの引数のloginFormに@Validatedを付与することで実現します。"login/success";}では、どこにバリデーション結果が保持されるの?、となると思います。この値はBindingResultに格納されます。具体的にはloginメソッドの引数にBindingResultを追加することで、バリデーション結果を受け取ることができるようになります。"login/success";}結果は受け取れるようになりましたのでエラーチェックを追加します。エラーチェックはBindingResult.hasErrors()で行えます。"login/success";}上記の例ではバリデーションエラーが存在する場合は/login/indexに遷移するようになります。この時点でHelloWorldControllerTestを実行してみます。“testIndex”は成功し、”loginの正常系”は失敗するようになるはずです。あれれ・・・、両方とも成功してしまいました。調べた結果ライブラリの組み合わせでバリデーションがうまく動作しないようです。4以前だとうまく動いていたのですが・・・と色々調べながら試行錯誤していくとglassfishのjavax.elを依存関係に追加するとうまくいくことがわかりました。3時間以上悩みました。com.sun.el.ExpressionFactoryImplが発生したことが問題解決の糸口でした。'1.10.19'}テストを実行すると期待する結果となりました。LoginControllerTestの修正loginの正常系の修正バリデーションにかからないようにuserNameを10桁、passwordを16桁に変更します。is(loginForm.getLoginPassword()));}テストを実行すると成功しました。バリデーションのテストを追加ユーザIDが空のときのテストを追加します。is(expErrorCodes.length));}詳細はコメントを記載しておりますので追加での説明は不要かと思います。テストしたい内容とは関係ないコードが非常に多いですが、実現できること自体がすごいですよね。その辺はバリエーションテストになるので共通化すれば良いだけです。is(expErrorCodes.length));}}かなりスッキリしました!あとはバリエーションを淡々と追加していくだけですのでloginの異常系_パスワードの文字種が不正だけ実装してみます。//文字種が不正なのでPatternがエラーコードとなります。password)).andExpect(status().isOk()).andExpect(view().name("login/index")).andExpect(model().hasErrors()).andExpect(model().errorCount(1)).andReturn();//文字種が不正なのでPatternがエラーコードとなります。bindingResult.getFieldErrors(targetMemberName);となります。再度実行すると成功しました。バリデーション時のメッセージのカスタマイズと多言語対応までいこかと思っていたのですが長くなりそうですので次回とさせていただきます。最後にLoginController.javaとHelloWorldControllerTest.javaを記載させていただきます。//文字種が不正なのでPatternがエラーコードとなります。password)).andExpect(status().isOk()).andExpect(view().name("login/index")).andExpect(model().hasErrors()).andExpect(model().errorCount(1)).andReturn();//文字種が不正なのでPatternがエラーコードとなります。Eclipse[2:プリミティブ型(基本データ型)とは]他のプログラミング言語と同様に、Javaにもデータ型が存在します。Java超入門の第2回では、プ記事を読むEclipseの使い方(Eclipse4.4のブックマーク機能とタスク機能)今回は、Eclipseのブックマーク機能とタスク機能の説明をさせていただきます。Eclipse[5:クラスに関する基礎知識(メソッドをJUnitを使って説明)]クラスに関する基礎知識シリーズも、いよいよメソッドを残すのみとなりました。8の新機能について」では、どんな新機能があるか紹介させていただきました。API」が利用できるようになりました。コメントをキャンセルメールアドレスが公開されることはありません。(4.7.1)を利用してJUnit5の公式ガイドの内容を実践してみる。JUnit5が本格的に利用できる環境が整ってきました。Suite)の環境作成と簡単なWebアプリの作成]Java、Eclipse、JUnitに関連した技術情報のブログです。