Spring Boot統合テストのためのSpring Security

1前書き

スタンドアロンの統合環境を必要とせずに統合テストを実行する機能は、あらゆるソフトウェアスタックにとって有益な機能です。 Spring BootとSpring Securityのシームレスな統合により、セキュリティレイヤと相互作用するコンポーネントを簡単にテストできます。

このクイックチュートリアルでは、 @ MockMvcTest @ SpringBootTest を使用してセキュリティ対応の統合テストを実行します。

2依存関係

まず、私たちの例に必要な依存関係を紹介しましょう。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-test</artifactId>
    <scope>test</scope>
</dependency>

https://search.maven.org/search?q = g:org.springframework.boot%20AND%20a:spring-boot-starter-web&core = gav[spring-boot-starter-web]、https://search.maven.org/search?q=g:org.springframework.boot%20AND%20a:spring-boot-starter-security&core=gav[spring-boot-starter-security], および __https://search.maven .org/search?q = g:org.springframework.boot%20AND%20a:spring-boot-starter-test&core = gav[spring-boot-start-test-test] __startersは、Spring MVC、Spring Security、およびSpring Securityへのアクセスを提供します。 Spring Bootテストユーティリティ

さらに、 https://search.maven.org/search?q = g:org.springframework.security%20AND 20a:spring-security-test&core = gav[spring-security-test] inを追加します。使用する @ WithMockUser アノテーションにアクセスするには

3 Webセキュリティ設定

私たちのWebセキュリティ設定は簡単です。認証されたユーザーだけが /private/ に一致するパスにアクセスできます。 /public/ に一致するパスはすべてのユーザーが利用できます。

@Configuration
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
        auth.inMemoryAuthentication()
         .passwordEncoder(encoder)
         .withUser("spring")
         .password(encoder.encode("secret"))
         .roles("USER");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
          .antMatchers("/private/** ** ")
          .authenticated()
          .antMatchers("/public/** ** ")
          .permitAll()
          .and()
          .httpBasic();
    }
}

4メソッドセキュリティ設定

__WebSecurityConfigurerで定義したURLパスベースのセキュリティに加えて、追加の設定ファイルを提供することでメソッドベースのセキュリティを設定できます。

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfigurer
  extends GlobalMethodSecurityConfiguration {
}

この設定により、Spring Securityのプリ/ポストアノテーションをサポートすることができます。追加のサポートが必要な場合は、他の属性も使用できます。 Spring Method Securityの詳細については、https://www.baeldung.com/spring-security-method-security[トピックに関する記事]を参照してください。

5 @ WebMvcTest を使用したコントローラのテスト

Spring Securityで @ WebMvcTest アノテーションアプローチを使用する場合、 MockMvc は、セキュリティ設定をテストするために必要な 必要なフィルタチェーンで自動的に設定されます。

MockMvc は私たちのために設定されているので、追加の設定なしでテストのために @ WithMockUser を使用することができます。

@RunWith(SpringRunner.class)
@WebMvcTest(SecuredController.class)
public class SecuredControllerWebMvcIntegrationTest {

    @Autowired
    private MockMvc mvc;

   //... other methods

    @WithMockUser(value = "spring")
    @Test
    public void givenAuthRequestOnPrivateService__shouldSucceedWith200() throws Exception {
        mvc.perform(get("/private/hello").contentType(MediaType.APPLICATION__JSON))
          .andExpect(status().isOk());
    }
}

@ WebMvcTest を使用すると、Spring Bootはコンテキスト全体ではなくWebレイヤのみをインスタンス化するように指示されます。このため、 __ @ WebMvcTestを使用するコントローラーテストは、他の方法よりも速く実行されます。

6. @ SpringBootTest を使用したコントローラのテスト

Spring Securityでコントローラをテストするために @ SpringBootTest アノテーションを使用する場合、** MockMvc を設定するときにフィルタチェーンを明示的に設定する必要があります。

これを行うには、 SecurityMockMvcConfigurer が提供する静的な springSecurity メソッドを使用することをお勧めします。

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM__PORT)
public class SecuredControllerSpringBootIntegrationTest {

    @Autowired
    private WebApplicationContext context;

    private MockMvc mvc;

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

   //... other methods

    @WithMockUser("spring")
    @Test
    public void givenAuthRequestOnPrivateService__shouldSucceedWith200() throws Exception {
        mvc.perform(get("/private/hello").contentType(MediaType.APPLICATION__JSON))
          .andExpect(status().isOk());
    }
}

7. @ SpringBootTest を使用して保護されたメソッドをテストする

保護されたメソッドをテストするために @ SpringBootTest を追加設定する必要はありません。 ** メソッドを直接呼び出すだけで、必要に応じて @ WithMockUser を使用できます。

@RunWith(SpringRunner.class)
@SpringBootTest
public class SecuredMethodSpringBootIntegrationTest {

    @Autowired
    private SecuredService service;

    @Test(expected = AuthenticationCredentialsNotFoundException.class)
    public void givenUnauthenticated__whenCallService__thenThrowsException() {
        service.sayHelloSecured();
    }

    @WithMockUser(username="spring")
    @Test
    public void givenAuthenticated__whenCallServiceWithSecured__thenOk() {
        assertThat(service.sayHelloSecured()).isNotBlank();
    }
}

8 @ SpringBootTest および TestRestTemplate を使用したテスト

TestRestTemplate は、保護されたRESTエンドポイントの統合テストを書くときに便利なオプションです。

保護されたエンドポイントを要求する前に、単にテンプレートを自動配線して資格情報を設定することができます。

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM__PORT)
public class SecuredControllerRestTemplateIntegrationTest {

    @Autowired
    private TestRestTemplate template;

   //... other methods

    @Test
    public void givenAuthRequestOnPrivateService__shouldSucceedWith200() throws Exception {
        ResponseEntity<String> result = template.withBasicAuth("spring", "secret")
          .getForEntity("/private/hello", String.class);
        assertEquals(HttpStatus.OK, result.getStatusCode());
    }
}

TestRestTemplate は柔軟で、セキュリティ関連の便利なオプションを数多く提供しています。 TestRestTemplate の詳細については、https://www.baeldung.com/spring-boot-testresttemplate[トピックに関する記事]を参照してください。

9結論

この記事では、セキュリティー対応の統合テストを実行するいくつかの方法について説明しました。

私たちは、mvccontrollerとRESTエンドポイントを使って、そしてセキュアなメソッドを使って作業する方法を調べました。

いつものように、ここに挙げた例のすべてのソースコードはhttps://github.com/eugenp/tutorials/tree/master/spring-boot-security[GitHubで見逃して]です。

  • **