かんがるーさんの日記

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

Spring Boot で書籍の貸出状況確認・貸出申請する Web アプリケーションを作る ( その16 )( ログイン画面の作成7 )

概要

Spring Boot で書籍の貸出状況確認・貸出申請する Web アプリケーションを作る ( その15 )( ログイン画面の作成6 ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • ログイン画面・ログアウト機能のテストクラスの作成 ( 前回からの続き )

参照したサイト・書籍

  1. Spring mvc 3.1 integration tests with session support
    http://stackoverflow.com/questions/13687055/spring-mvc-3-1-integration-tests-with-session-support

    • MockMvc に session を引き継ぐ方法を調査した時に参照しました。
  2. spring-projects/spring-test-mvc - Mockito and MockHttpServletRequest #57
    https://github.com/spring-projects/spring-test-mvc/issues/57

    • 「次回から自動的にログインするのテスト」のテストメソッドを実装する際に、remember-me parameter を渡す方法を調査した時に参照しました。記事の中に書かれていた SimpleRequestBuilder をそのまま利用しています。

目次

  1. SecurityMockMvcResource クラスの準備
  2. LoginControllerTest クラスの作成
  3. commit、Push、Pull Request、マージ
  4. 次回は。。。

手順

SecurityMockMvcResource クラス、SecurityMockMvcLoginErrorResource クラスの準備

  1. src/test/java/ksbysample/common/test の下の SecurityMockMvcResource.javaリンク先の内容 に変更します。

LoginControllerTest クラスの作成

  1. src/main/java/ksbysample/webapp/lending/web の下の LoginController.java を開いて「Create Test」ダイアログを表示し、テストクラスを作成します。

    f:id:ksby:20150809192330p:plain

    • 画面下部の Member 一覧は何もチェックしません。自分でテストメソッドを書きます。

    src/test/java/ksbysample/webapp/lending/web の下に LoginControllerTest.java が作成されます。

  2. 最初にテストクラスの構造のみ記載します。src/test/java/ksbysample/webapp/lending/web の下の LoginControllerTest.javaリンク先のその1の内容 に変更します。

  3. remember-me 機能のテストを実装するために必要な SimpleRequestBuilder クラスを作成します。src/test/java/ksbysample/common/test の下に SimpleRequestBuilder.java を作成します。作成後、リンク先の内容 に変更します。

    ※SimpleRequestBuilder クラスは spring-projects/spring-test-mvc - Mockito and MockHttpServletRequest #57 の中に書かれていたものをそのまま使います。

  4. テストを実装します。src/test/java/ksbysample/webapp/lending/web の下の LoginControllerTest.javaリンク先のその2の内容 に変更します。以下に苦労した点を記載します。

    • 「次回から自動的にログインするのテスト」で Spring Security の formLogin() を使用しつつ、かつ独自パラメータ ( remember-me ) を渡す方法が本当に分かりませんでした。内容はソースに書いた通りですが、もっと簡単な方法がないのかいまだに疑問です。。。 何度もパラメータを渡す場合にはヘルパークラスを作成した方がよいでしょう。
    • ログインした状態を MockMvc に引き継ぐ方法が最初分かりませんでした。結論としては MvcResult result を取得してから result.getRequest().getSession() を呼び出して HttpSession session を取得し、次のアクセス時に session メソッドに渡せば引き継ぐことができました。
  5. テストを実行してみます。LoginControllerTest のクラス名にカーソルを移動し、コンテキストメニューを表示後「Run 'LoginControllerTest' with Coverage」を選択します。

    テストが全て成功することが確認できます。

    f:id:ksby:20150812224714p:plain

commit、Push、Pull Request、マージ

  1. commit します。「Code Analysis」ダイアログが出ますが、無視して「Commit」ボタンをクリックします。

  2. コマンドラインから以下のコマンドを実行して commit を1つにまとめます。

    > git rebase -i HEAD~3
    > git commit --amend -m "#19 ログイン画面のテストクラスを作成しました。"

  3. GitHub へ Push、1.0.x-make-test-login -> 1.0.x へ Pull Request、1.0.x でマージ、1.0.x-make-test-login ブランチを削除、をします。

次回は。。。

画面の共通部分を作成します。

今回テストを作成していて /urllogin で enabled やアカウント/パスワードの有効期限等を見ていないことに気づいたのですが、今はこのままにします。一旦ログイン画面から離れたい。。。

ソースコード

SecurityMockMvcResource.java

package ksbysample.common.test;

import org.junit.rules.ExternalResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import javax.servlet.Filter;

import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;

@Component
public class SecurityMockMvcResource extends ExternalResource {

    public final String MAILADDR_TANAKA_TARO = "tanaka.taro@sample.com";
    public final String MAILADDR_SUZUKI_HANAKO = "suzuki.hanako@test.co.jp";
    public final String MAILADDR_KIMURA_MASAO = "kimura.masao@test.co.jp";
    public final String MAILADDR_ENDO_YOKO = "endo.yoko@sample.com";
    public final String MAILADDR_SATO_MASAHIKO = "sato.masahiko@sample.com";
    public final String MAILADDR_TAKAHASI_NAOKO = "takahasi.naoko@test.co.jp";

    @Autowired
    private WebApplicationContext context;

    @Autowired
    private Filter springSecurityFilterChain;

    @Autowired
    private UserDetailsService userDetailsService;

    public MockMvc authTanakaTaro;
    public MockMvc authSuzukiHanako;
    public MockMvc noauth;

    @Override
    protected void before() throws Throwable {
        // 認証ユーザ用MockMvc ( user = tanaka.taro@sample.com )
        UserDetails userDetailsTanakaTaro = userDetailsService.loadUserByUsername(MAILADDR_TANAKA_TARO);
        this.authTanakaTaro = MockMvcBuilders.webAppContextSetup(this.context)
                .defaultRequest(get("/").with(user(userDetailsTanakaTaro)))
                .addFilter(springSecurityFilterChain)
                .build();

        // 認証ユーザ用MockMvc ( user = suzuki.hanako@test.co.jp )
        UserDetails userDetailsSuzukiHanako = userDetailsService.loadUserByUsername(MAILADDR_SUZUKI_HANAKO);
        this.authSuzukiHanako = MockMvcBuilders.webAppContextSetup(this.context)
                .defaultRequest(get("/").with(user(userDetailsSuzukiHanako)))
                .addFilter(springSecurityFilterChain)
                .build();

        // 非認証ユーザ用MockMvc
        this.noauth = MockMvcBuilders.webAppContextSetup(this.context)
                .addFilter(springSecurityFilterChain)
                .build();
    }

}
  • 認証ユーザ用MockMvc も作っていますが、今回のテストでは非認証ユーザ用MockMvc の方しか使っていません。
  • 認証ユーザ用MockMvc では .defaultRequest(get("/").with(user(...).roles(...))) の形式ではなく、UserDetails クラスのインスタンスを生成してから .defaultRequest(get("/").with(user(UserDetails クラスのインスタンス))) の形式で実装しています。

LoginControllerTest.java

■その1

package ksbysample.webapp.lending.web;

import ksbysample.webapp.lending.Application;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;

@RunWith(Enclosed.class)
public class LoginControllerTest {

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = Application.class)
    @WebAppConfiguration
    public static class ログイン画面の初期表示のテスト {

    }

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = Application.class)
    @WebAppConfiguration
    public static class ログイン成功のテスト {

    }

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = Application.class)
    @WebAppConfiguration
    public static class ログインエラーのテスト {

    }

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = Application.class)
    @WebAppConfiguration
    public static class 次回から自動的にログインするのテスト {

    }

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = Application.class)
    @WebAppConfiguration
    public static class ログアウトのテスト {

    }

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = Application.class)
    @WebAppConfiguration
    public static class encodeのテスト {

    }

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = Application.class)
    @WebAppConfiguration
    public static class urlloginのテスト {

    }

}

■その2

package ksbysample.webapp.lending.web;

import ksbysample.common.test.SecurityMockMvcResource;
import ksbysample.common.test.SimpleRequestBuilder;
import ksbysample.common.test.TestDataResource;
import ksbysample.webapp.lending.Application;
import ksbysample.webapp.lending.config.WebSecurityConfig;
import ksbysample.webapp.lending.dao.UserInfoDao;
import ksbysample.webapp.lending.entity.UserInfo;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.mock.web.MockHttpSession;
import org.springframework.mock.web.MockServletContext;
import org.springframework.security.authentication.*;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MvcResult;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpSession;

import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.CoreMatchers.isA;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated;
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@RunWith(Enclosed.class)
public class LoginControllerTest {

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = Application.class)
    @WebAppConfiguration
    public static class ログイン画面の初期表示のテスト {

        @Rule
        @Autowired
        public TestDataResource testDataResource;

        @Rule
        @Autowired
        public SecurityMockMvcResource mvc;

        @Test
        public void ログイン画面を表示する() throws Exception {
            // ログイン画面が表示されることを確認する
            mvc.noauth.perform(get("/"))
                    .andExpect(status().isOk())
                    .andExpect(content().contentType("text/html;charset=UTF-8"))
                    .andExpect(view().name("login"))
                    .andExpect(model().hasNoErrors());
        }

    }

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = Application.class)
    @WebAppConfiguration
    public static class ログイン成功のテスト {

        @Rule
        @Autowired
        public TestDataResource testDataResource;

        @Rule
        @Autowired
        public SecurityMockMvcResource mvc;

        @Test
        public void 有効なユーザ名とパスワードを入力すればログインに成功する() throws Exception {
            mvc.noauth.perform(formLogin()
                            .user("id", mvc.MAILADDR_TANAKA_TARO)
                            .password("password", "taro")
            )
                    .andExpect(status().isFound())
                    .andExpect(redirectedUrl(WebSecurityConfig.DEFAULT_SUCCESS_URL))
                    .andExpect(authenticated().withUsername(mvc.MAILADDR_TANAKA_TARO));
        }

    }

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = Application.class)
    @WebAppConfiguration
    public static class ログインエラーのテスト {

        @Rule
        @Autowired
        public TestDataResource testDataResource;

        @Rule
        @Autowired
        public SecurityMockMvcResource mvc;

        @Autowired
        private UserInfoDao userInfoDao;

        @Test
        public void 存在しないユーザ名とパスワードを入力すればログインはエラーになる() throws Exception {
            mvc.noauth.perform(formLogin()
                            .user("id", "user.notexists@sample.com")
                            .password("password", "notexists")
            )
                    .andExpect(status().isFound())
                    .andExpect(redirectedUrl("/"))
                    .andExpect(unauthenticated())
                    .andExpect(request().sessionAttribute("SPRING_SECURITY_LAST_EXCEPTION", isA(BadCredentialsException.class)));
        }

        @Test
        public void 存在するユーザ名でもパスワードが正しくなければログインはエラーになる() throws Exception {
            mvc.noauth.perform(formLogin()
                            .user("id", mvc.MAILADDR_TANAKA_TARO)
                            .password("password", "tanaka")
            )
                    .andExpect(status().isFound())
                    .andExpect(redirectedUrl("/"))
                    .andExpect(unauthenticated())
                    .andExpect(request().sessionAttribute("SPRING_SECURITY_LAST_EXCEPTION", isA(BadCredentialsException.class)));
        }

        @Test
        public void enabledが0のユーザならばログインはエラーになる() throws Exception {
            mvc.noauth.perform(formLogin()
                            .user("id", mvc.MAILADDR_KIMURA_MASAO)
                            .password("password", "masao")
            )
                    .andExpect(status().isFound())
                    .andExpect(redirectedUrl("/"))
                    .andExpect(unauthenticated())
                    .andExpect(request().sessionAttribute("SPRING_SECURITY_LAST_EXCEPTION", isA(DisabledException.class)));
        }

        @Test
        public void アカウントの有効期限が切れているユーザならばログインはエラーになる() throws Exception {
            mvc.noauth.perform(formLogin()
                            .user("id", mvc.MAILADDR_ENDO_YOKO)
                            .password("password", "yoko")
            )
                    .andExpect(status().isFound())
                    .andExpect(redirectedUrl("/"))
                    .andExpect(unauthenticated())
                    .andExpect(request().sessionAttribute("SPRING_SECURITY_LAST_EXCEPTION", isA(AccountExpiredException.class)));
        }

        @Test
        public void パスワードの有効期限が切れているユーザならばログインはエラーになる() throws Exception {
            mvc.noauth.perform(formLogin()
                            .user("id", mvc.MAILADDR_SATO_MASAHIKO)
                            .password("password", "masahiko")
            )
                    .andExpect(status().isFound())
                    .andExpect(redirectedUrl("/"))
                    .andExpect(unauthenticated())
                    .andExpect(request().sessionAttribute("SPRING_SECURITY_LAST_EXCEPTION", isA(CredentialsExpiredException.class)));
        }

        @Test
        public void ログインを5回失敗すればアカウントはロックされる() throws Exception {
            // 1回目
            mvc.noauth.perform(formLogin()
                            .user("id", mvc.MAILADDR_TANAKA_TARO)
                            .password("password", "taro1")
            )
                    .andExpect(status().isFound())
                    .andExpect(redirectedUrl("/"))
                    .andExpect(unauthenticated())
                    .andExpect(request().sessionAttribute("SPRING_SECURITY_LAST_EXCEPTION", isA(BadCredentialsException.class)));
            UserInfo userInfo = userInfoDao.selectByMailAddress(mvc.MAILADDR_TANAKA_TARO);
            assertThat(userInfo.getCntBadcredentials()).isEqualTo((short) 1);

            // 2回目
            mvc.noauth.perform(formLogin()
                            .user("id", mvc.MAILADDR_TANAKA_TARO)
                            .password("password", "taro2")
            )
                    .andExpect(status().isFound())
                    .andExpect(redirectedUrl("/"))
                    .andExpect(unauthenticated())
                    .andExpect(request().sessionAttribute("SPRING_SECURITY_LAST_EXCEPTION", isA(BadCredentialsException.class)));
            userInfo = userInfoDao.selectByMailAddress(mvc.MAILADDR_TANAKA_TARO);
            assertThat(userInfo.getCntBadcredentials()).isEqualTo((short) 2);

            // 3回目
            mvc.noauth.perform(formLogin()
                            .user("id", mvc.MAILADDR_TANAKA_TARO)
                            .password("password", "taro3")
            )
                    .andExpect(status().isFound())
                    .andExpect(redirectedUrl("/"))
                    .andExpect(unauthenticated())
                    .andExpect(request().sessionAttribute("SPRING_SECURITY_LAST_EXCEPTION", isA(BadCredentialsException.class)));
            userInfo = userInfoDao.selectByMailAddress(mvc.MAILADDR_TANAKA_TARO);
            assertThat(userInfo.getCntBadcredentials()).isEqualTo((short) 3);

            // 4回目
            mvc.noauth.perform(formLogin()
                            .user("id", mvc.MAILADDR_TANAKA_TARO)
                            .password("password", "taro4")
            )
                    .andExpect(status().isFound())
                    .andExpect(redirectedUrl("/"))
                    .andExpect(unauthenticated())
                    .andExpect(request().sessionAttribute("SPRING_SECURITY_LAST_EXCEPTION", isA(BadCredentialsException.class)));
            userInfo = userInfoDao.selectByMailAddress(mvc.MAILADDR_TANAKA_TARO);
            assertThat(userInfo.getCntBadcredentials()).isEqualTo((short) 4);

            // 5回目 ( ここまでは BadCredentialsException.class )
            mvc.noauth.perform(formLogin()
                            .user("id", mvc.MAILADDR_TANAKA_TARO)
                            .password("password", "taro5")
            )
                    .andExpect(status().isFound())
                    .andExpect(redirectedUrl("/"))
                    .andExpect(unauthenticated())
                    .andExpect(request().sessionAttribute("SPRING_SECURITY_LAST_EXCEPTION", isA(BadCredentialsException.class)));
            userInfo = userInfoDao.selectByMailAddress(mvc.MAILADDR_TANAKA_TARO);
            assertThat(userInfo.getCntBadcredentials()).isEqualTo((short) 5);

            // 6回目 ( アカウントがロックされているので LockedException.class に変わる )
            mvc.noauth.perform(formLogin()
                            .user("id", mvc.MAILADDR_TANAKA_TARO)
                            .password("password", "taro6")
            )
                    .andExpect(status().isFound())
                    .andExpect(redirectedUrl("/"))
                    .andExpect(unauthenticated())
                    .andExpect(request().sessionAttribute("SPRING_SECURITY_LAST_EXCEPTION", isA(LockedException.class)));
            userInfo = userInfoDao.selectByMailAddress(mvc.MAILADDR_TANAKA_TARO);
            assertThat(userInfo.getCntBadcredentials()).isEqualTo((short) 5);
        }

    }

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = Application.class)
    @WebAppConfiguration
    public static class 次回から自動的にログインするのテスト {

        @Rule
        @Autowired
        public TestDataResource testDataResource;

        @Rule
        @Autowired
        public SecurityMockMvcResource mvc;

        @Test
        public void 次回から自動的にログインするをチェックすれば次はログインしていなくてもログイン後の画面にアクセスできる()
                throws Exception {
            // ログイン前にはログイン後の画面にアクセスできない
            mvc.noauth.perform(get(WebSecurityConfig.DEFAULT_SUCCESS_URL))
                    .andExpect(status().isFound())
                    .andExpect(redirectedUrl("http://localhost/"))
                    .andExpect(unauthenticated());

            // 「次回から自動的にログインする」をチェックしてログインし、remember-me Cookie を生成する
            MockServletContext servletContext = new MockServletContext();
            org.springframework.mock.web.MockHttpServletRequest request
                    = formLogin()
                    .user("id", mvc.MAILADDR_TANAKA_TARO)
                    .password("password", "taro")
                    .buildRequest(servletContext);
            request.addParameter("remember-me", "true");
            SimpleRequestBuilder simpleRequestBuilder = new SimpleRequestBuilder(request);
            MvcResult result = mvc.noauth.perform(simpleRequestBuilder)
                    .andExpect(status().isFound())
                    .andExpect(redirectedUrl("/loginsuccess"))
                    .andExpect(authenticated().withUsername(mvc.MAILADDR_TANAKA_TARO))
                    .andReturn();
            Cookie[] cookie = result.getResponse().getCookies();

            // remember-me Cookie を引き継いでログイン後の画面にアクセスするとアクセスできる
            mvc.noauth.perform(get(WebSecurityConfig.DEFAULT_SUCCESS_URL).cookie(cookie))
                    .andExpect(status().isOk())
                    .andExpect(content().contentType("text/html;charset=UTF-8"))
                    .andExpect(view().name("loginsuccess"))
                    .andExpect(model().hasNoErrors())
                    .andExpect(authenticated().withUsername(mvc.MAILADDR_TANAKA_TARO));

            // ログイン画面にアクセスしても有効な remember-me Cookie があればログイン後の画面にリダイレクトする 
            mvc.noauth.perform(get("/").cookie(cookie))
                    .andExpect(status().isFound())
                    .andExpect(redirectedUrl("/loginsuccess"))
                    .andExpect(authenticated().withUsername(mvc.MAILADDR_TANAKA_TARO));
        }

    }

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = Application.class)
    @WebAppConfiguration
    public static class ログアウトのテスト {

        @Rule
        @Autowired
        public TestDataResource testDataResource;

        @Rule
        @Autowired
        public SecurityMockMvcResource mvc;

        @Test
        public void 有効なユーザ名とパスワードを入力すればログインに成功する() throws Exception {
            // ログイン前にはログイン後の画面にアクセスできない
            mvc.noauth.perform(get(WebSecurityConfig.DEFAULT_SUCCESS_URL))
                    .andExpect(status().isFound())
                    .andExpect(redirectedUrl("http://localhost/"))
                    .andExpect(unauthenticated());

            // ログインする
            MvcResult result = mvc.noauth.perform(formLogin()
                            .user("id", mvc.MAILADDR_TANAKA_TARO)
                            .password("password", "taro")
            )
                    .andExpect(status().isFound())
                    .andExpect(redirectedUrl(WebSecurityConfig.DEFAULT_SUCCESS_URL))
                    .andExpect(authenticated().withUsername(mvc.MAILADDR_TANAKA_TARO))
                    .andReturn();
            HttpSession session = result.getRequest().getSession();
            assertThat(session).isNotNull();

            // ログインしたのでログイン後の画面にアクセスできる
            mvc.noauth.perform(get(WebSecurityConfig.DEFAULT_SUCCESS_URL).session((MockHttpSession) session))
                    .andExpect(status().isOk())
                    .andExpect(content().contentType("text/html;charset=UTF-8"))
                    .andExpect(view().name("loginsuccess"))
                    .andExpect(model().hasNoErrors())
                    .andExpect(authenticated().withUsername(mvc.MAILADDR_TANAKA_TARO));

            // ログアウトする
            mvc.noauth.perform(get("/logout").session((MockHttpSession) session))
                    .andExpect(status().isFound())
                    .andExpect(redirectedUrl("/"))
                    .andExpect(unauthenticated());

            // ログアウトしたのでログイン後の画面にアクセスできない
            mvc.noauth.perform(get(WebSecurityConfig.DEFAULT_SUCCESS_URL).session((MockHttpSession) session))
                    .andExpect(status().isFound())
                    .andExpect(redirectedUrl("http://localhost/"))
                    .andExpect(unauthenticated());
        }

    }

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = Application.class)
    @WebAppConfiguration
    public static class urlloginのテスト {

        @Rule
        @Autowired
        public TestDataResource testDataResource;

        @Rule
        @Autowired
        public SecurityMockMvcResource mvc;

        @RunWith(SpringJUnit4ClassRunner.class)
        @SpringApplicationConfiguration(classes = Application.class)
        @WebAppConfiguration
        public static class encodeのテスト {

            @Rule
            @Autowired
            public SecurityMockMvcResource mvc;

            @Test
            public void encodeで生成したパスワードの暗号化文字列が正しいことを確認する() throws Exception {
                MvcResult result = mvc.noauth.perform(get("/encode?password=ptest"))
                        .andExpect(status().isOk())
                        .andExpect(content().contentType("text/plain;charset=UTF-8"))
                        .andReturn();
                String crypt = result.getResponse().getContentAsString();
                BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
                assertThat(passwordEncoder.matches("ptest", crypt)).isTrue();
            }

        }

        @Test
        public void 存在するメールアドレスを指定すればログインに成功する() throws Exception {
            // ログイン前にはログイン後の画面にアクセスできない
            mvc.noauth.perform(get(WebSecurityConfig.DEFAULT_SUCCESS_URL))
                    .andExpect(status().isFound())
                    .andExpect(redirectedUrl("http://localhost/"))
                    .andExpect(unauthenticated());

            // 存在するメールアドレスを指定して /urllogin にアクセスすればログインできる
            MvcResult result = mvc.noauth.perform(get("/urllogin?user=" + mvc.MAILADDR_TANAKA_TARO))
                    .andExpect(status().isFound())
                    .andExpect(redirectedUrl(WebSecurityConfig.DEFAULT_SUCCESS_URL))
                    .andExpect(authenticated().withUsername(mvc.MAILADDR_TANAKA_TARO))
                    .andReturn();
            HttpSession session = result.getRequest().getSession();
            assertThat(session).isNotNull();

            // ログイン後の画面にアクセスしてもエラーにならない
            mvc.noauth.perform(get(WebSecurityConfig.DEFAULT_SUCCESS_URL).session((MockHttpSession) session))
                    .andExpect(status().isOk())
                    .andExpect(content().contentType("text/html;charset=UTF-8"))
                    .andExpect(view().name("loginsuccess"))
                    .andExpect(model().hasNoErrors())
                    .andExpect(authenticated().withUsername(mvc.MAILADDR_TANAKA_TARO));
        }

    }

}

SimpleRequestBuilder.java

package ksbysample.common.test;

import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.test.web.servlet.RequestBuilder;

import javax.servlet.ServletContext;

public class SimpleRequestBuilder implements RequestBuilder {

    private final MockHttpServletRequest request;

    public SimpleRequestBuilder(MockHttpServletRequest request) {
        this.request = request;
    }

    public MockHttpServletRequest buildRequest(ServletContext servletContext) {
        return request;
    }

}

履歴

2015/08/12
初版発行。