web-dev-qa-db-ja.com

MockMvcを使用したSpringMVCでのユニットテスト/ログイン

私は非常に単純なREST Spring MVCを使用して作成されたアプリケーションを持っています。(コードは GitHub で入手できます。)単純な WebSecurityConfigurer 次のように:

@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
    httpSecurity
            .csrf().disable()
            .exceptionHandling()
                .authenticationEntryPoint(authenticationEntryPoint)
                .and()
            .authorizeRequests()
                .antMatchers("/user/new").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login").permitAll()
                .successHandler(authenticationSuccessHandler)
                .failureHandler(authenticationFailureHandler)
                .and()
            .logout()
                .permitAll()
                .logoutSuccessHandler(logoutSuccessHandler);
}

アプリケーションを実行すると、カスタムコントローラーとログイン/ログアウトページの両方が問題なく機能します。 ユニットテスト/user/newMockMvc経由でも可能です。しかし、次の関数で/loginをテストしようとすると

@Test
public void testUserLogin() throws Exception {
    RequestBuilder requestBuilder = post("/login")
            .param("username", testUser.getUsername())
            .param("password", testUser.getPassword());
    mockMvc.perform(requestBuilder)
            .andDo(print())
            .andExpect(status().isOk())
            .andExpect(cookie().exists("JSESSIONID"));
}

次のように失敗します。

MockHttpServletRequest:
         HTTP Method = POST
         Request URI = /login
          Parameters = {username=[test-user-UserControllerTest], password=[test-user-UserControllerTest-password]}
             Headers = {}

             Handler:
                Type = org.springframework.web.servlet.resource.ResourceHttpRequestHandler

               Async:
   Was async started = false
        Async result = null

  Resolved Exception:
                Type = org.springframework.web.HttpRequestMethodNotSupportedException

        ModelAndView:
           View name = null
                View = null
               Model = null

            FlashMap:

MockHttpServletResponse:
              Status = 405
       Error message = Request method 'POST' not supported
             Headers = {Allow=[HEAD, GET]}
        Content type = null
                Body = 
       Forwarded URL = null
      Redirected URL = null
             Cookies = []

Java.lang.AssertionError: Status expected:<200> but was:<405>

しかし、私はかなりのユーザーですPOSTから/loginは、テストではなくアプリケーションを実行すると機能します。さらに、(ログのHeaders = {Allow=[HEAD, GET]}行に示されているように)GETまたはHEADリクエストを実行しようとすると、今回は404を受け取ります。で、どうすれば修正できますか?

10
Volkan Yazıcı

Githubリンクに気づきました。テストにもセキュリティフィルターを設定する必要があると思います。何かのようなもの

 mockMvc = MockMvcBuilders.webApplicationContextSetup(webApplicationContext)
                .addFilter(springSecurityFilterChain)
                .build();

いくつかの追加設定が必要になる場合があります。インスピレーションを得るために http://www.petrikainulainen.net/programming/spring-framework/integration-testing-of-spring-mvc-applications-security/ を確認してください。

7
sodik

Springセキュリティテストクラスを使用して、フォームベースのログインをテストできます。フォームベースのログインをテストするには、次の手順を実行する必要があります。

Mavenの依存関係:

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-test</artifactId>
    <version>4.0.0.M1</version>
    <scope>test</scope>
</dependency>

<repositories>
    <repository>
        <id>spring-snasphot</id>
        <url>https://repo.spring.io/libs-snapshot</url>
    </repository>
</repositories>

テストクラス:

import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;

RequestBuilder requestBuilder = formLogin().user("username").password("passowrd");
mockMvc.perform(requestBuilder)
    .andDo(print())
    .andExpect(status().isOk())
    .andExpect(cookie().exists("JSESSIONID"));
6
Mithun

SpringSessionをテストして、セッションCookieを取得し、これを実行して組み込みRedisにセッションを保存することを達成しました。

@Autowired
private SessionRepositoryFilter<?> springSessionRepositoryFilter;
...

@Before
public void setup() {
    mvc = MockMvcBuilders
        .webAppContextSetup(context)
        .addFilters(springSessionRepositoryFilter)
        .apply(springSecurity())
        .build();
}

それが役に立てば幸い。

1
jpadilladev

ここに私の投稿に従ってください: Spring MockMvcBuildersセキュリティフィルター

REST API with UsernamePasswordAuthenticationToken for/oauth/tokenを作成できましたが、保護されたリソースのテストを作成できませんでした(実行中のサーバーでは正常に動作します)。あなたのRESTインターフェース?

1
Pegazus