かんがるーさんの日記

最近自分が興味をもったものを調べた時の手順等を書いています。今は Spring Boot をいじっています。

Spring Boot 1.2.x の Web アプリを 1.3.x へバージョンアップする ( その4 )( build.gradle 修正後のテストが失敗する原因を解消する )

概要

Spring Boot 1.2.x の Web アプリを 1.3.x へバージョンアップする ( その3 )( build.gradle 修正後の Rebuild で出た Warning を解消する ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • build.gradle 修正後のテストが失敗する原因の解消

参照したサイト・書籍

  1. Spring Boot 1.3.2 released
    https://spring.io/blog/2016/01/22/spring-boot-1-3-2-released

    • messages.properties まわりの仕様変更について参照しました。

目次

  1. LoginControllerTest.java
    1. 存在しないユーザ名とパスワードを入力すればログインはエラーになる
    2. 有効なユーザ名とパスワードを入力すればログインに成功する
  2. 動作確認
  3. 次回は。。。

手順

LoginControllerTest.java

LoginControllerTest.java の以下のテストメソッドでエラーが出ているので修正します。

f:id:ksby:20160520012008p:plain

存在しないユーザ名とパスワードを入力すればログインはエラーになる

表示されたエラーメッセージは以下の内容でした。

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' の方でした。以下の記事に書かれてありますが、

Spring Boot 1.3.2 released

1.3.2 から messages.properties というファイルがないと messageSource の auto-configuration が実行されないため、このエラーメッセージが出ていました。src/main/resources の下に messages.properties を作成します ( ファイルの中は空っぽです )。

f:id:ksby:20160520004545p:plain

有効なユーザ名とパスワードを入力すればログインに成功する

表示されたエラーメッセージは以下の内容でした。

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 が返っていることが確認できます。

f:id:ksby:20160518202847p:plain

1.0.x ブランチをチェックアウトした後、Gradle projects View の左上にある「Refresh all Gradle projects」ボタンをクリックして更新 → clean → Rebuild します。

さきほどと同じようにテストを debug 実行してみると、今度は null ではありませんでした。

f:id:ksby:20160518203453p:plain

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 を実行すると以下のように全てのテストが成功しました。

f:id:ksby:20160520013632p:plain

次回は。。。

1.3系ではこう書くべきという点があるか確認し、変更した方がよいところを修正します。

ソースコード

履歴

2016/05/20
初版発行。