Spring Boot 1.2.x の Web アプリを 1.3.x へバージョンアップする ( その4 )( build.gradle 修正後のテストが失敗する原因を解消する )
概要
- 今回の手順で確認できるのは以下の内容です。
- build.gradle 修正後のテストが失敗する原因の解消
参照したサイト・書籍
Spring Boot 1.3.2 released
https://spring.io/blog/2016/01/22/spring-boot-1-3-2-released- messages.properties まわりの仕様変更について参照しました。
目次
手順
LoginControllerTest.java
LoginControllerTest.java の以下のテストメソッドでエラーが出ているので修正します。
存在しないユーザ名とパスワードを入力すればログインはエラーになる
表示されたエラーメッセージは以下の内容でした。
java.lang.AssertionError: Session attribute 'SPRING_SECURITY_LAST_EXCEPTION' Expected: is an instance of org.springframework.security.authentication.BadCredentialsException but: <org.springframework.security.authentication.InternalAuthenticationServiceException: No message found under code 'UserInfoUserDetailsService.usernameNotFound' for locale 'ja_JP'.> is a org.springframework.security.authentication.InternalAuthenticationServiceException at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20) at org.springframework.test.web.servlet.result.RequestResultMatchers$7.match(RequestResultMatchers.java:154) at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:171) at ksbysample.webapp.lending.web.LoginControllerTest$ログインエラーのテスト.存在しないユーザ名とパスワードを入力すればログインはエラーになる(LoginControllerTest.java:115) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.lang.reflect.Method.invoke(Method.java:498) ..........
最初 BadCredentialsException が InternalAuthenticationServiceException に変更されたのかと思っていたのですが、本当の問題は No message found under code 'UserInfoUserDetailsService.usernameNotFound' for locale 'ja_JP'
の方でした。以下の記事に書かれてありますが、
1.3.2 から messages.properties というファイルがないと messageSource の auto-configuration が実行されないため、このエラーメッセージが出ていました。src/main/resources の下に messages.properties を作成します ( ファイルの中は空っぽです )。
有効なユーザ名とパスワードを入力すればログインに成功する
表示されたエラーメッセージは以下の内容でした。
java.lang.NullPointerException at java.util.Objects.requireNonNull(Objects.java:203) at java.util.Arrays$ArrayList.<init>(Arrays.java:3813) at java.util.Arrays.asList(Arrays.java:3800) at ksbysample.webapp.lending.util.cookie.CookieUtils.getCookieValue(CookieUtils.java:36) at ksbysample.webapp.lending.helper.url.UrlAfterLoginHelper.getUrlAfterLogin(UrlAfterLoginHelper.java:31) at ksbysample.webapp.lending.security.RoleAwareAuthenticationSuccessHandler.onAuthenticationSuccess(RoleAwareAuthenticationSuccessHandler.java:31) at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.successfulAuthentication(AbstractAuthenticationProcessingFilter.java:331) at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:245) ..........
at ksbysample.webapp.lending.util.cookie.CookieUtils.getCookieValue(CookieUtils.java:36)
のソースを見てみると、以下のように実装していました。
public static String getCookieValue(String cookieName, HttpServletRequest request) { Optional<String> result = Optional.empty(); if (request != null) { Cookie[] cookies = request.getCookies(); result = Arrays.asList(cookies).stream() ← エラーが出ている CookieUtils.java:36 はここ .filter(cookie -> StringUtils.equals(cookie.getName(), cookieName)) .map(cookie -> cookie.getValue()) .findFirst(); } return result.orElse(null); }
確かに言われてみれば Cookie[] cookies = request.getCookies();
の後で cookies の null チェックが必要ですね。でも前は null ではなかったのでしょうか? 確認してみます。
breakpoint を設定してテストを debug 実行してみると、確かに cookies には null が返っていることが確認できます。
1.0.x ブランチをチェックアウトした後、Gradle projects View の左上にある「Refresh all Gradle projects」ボタンをクリックして更新 → clean → Rebuild します。
さきほどと同じようにテストを debug 実行してみると、今度は null ではありませんでした。
1.1.x-springboot-1.2-to-1.3 ブランチをチェックアウトした後、Gradle projects View の左上にある「Refresh all Gradle projects」ボタンをクリックして更新 → clean → Rebuild して元に戻します。
src/main/java/ksbysample/webapp/lending/util/cookie/CookieUtils.java を以下のように変更します。
public static String getCookieValue(String cookieName, HttpServletRequest request) { Optional<String> result = Optional.empty(); if (request != null) { Cookie[] cookies = request.getCookies(); if (cookies != null) { result = Arrays.asList(cookies).stream() .filter(cookie -> StringUtils.equals(cookie.getName(), cookieName)) .map(cookie -> cookie.getValue()) .findFirst(); } } return result.orElse(null); }
result = Arrays.asList(cookies).stream()...
をif (cookies != null) { ... }
で囲みます。
動作確認
失敗していたテストは21個ありましたが、問題だったのは上の2点だけでした。Project View の src/test から Run 'All Tests' with Coverage を実行すると以下のように全てのテストが成功しました。
次回は。。。
1.3系ではこう書くべきという点があるか確認し、変更した方がよいところを修正します。
ソースコード
履歴
2016/05/20
初版発行。