MockMvc を使用して Spring Boot アプリケーションをテストする際に問題が発生しています。
次のテストクラスがあります。
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {SpringConfiguration.class, SecurityConfiguration.class})
@IntegrationTest({"server.port=8080"})
@WebAppConfiguration
public class DemoTest {
@Autowired
private EmbeddedWebApplicationContext webApplicationContext;
private MockMvc mockMvc;
@Before
public void setUp() throws Exception {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
@Test
public void testGetAccountUnauthenticated() throws Exception {
mockMvc.perform(get("/accounts/1").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isUnauthorized());
}
}
これにより、401 ではなく HTTP 200 が返されます。コンポーネントのスキャンと自動構成が有効になっており、Spring セキュリティが SecuityConfiguration クラスで次のように構成されています。
@Configuration
@EnableWebSecurity
@EnableWebMvcSecurity // required for use of @AuthenticationPrincipal in MVC controllers.
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) {
web.debug(true);
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
//set up authentication.
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated();
// set up form login
}
}
RestTemplate を使用してアクセスするhttp://localhost:8080/accounts/1
と、期待される動作 (HTTP 401) が得られます。
メソッドを使用して手動でフィルターを自動配線し、追加することを示唆する他の例 (テスト用の Spring Boot セットアップ セキュリティなど) を見てきました。ただし、これは実際には失敗します ( )。FilterChainProxy
WebApplicationContext.addFilters(filterChainProxy)
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.security.web.FilterChainProxy] found
2 つの質問があります。
- 注入された WebApplicationContext が SpringSecurity フィルターを自動的に使用しないのはなぜですか? FilterChainProxy を取得して手動で追加できたとしても、EmbeddedWebApplicationContext の JavaDoc には次のように記載されています。
コンテキストで定義された {@link Servlet} または {@link Filter} Bean は、組み込みサーブレット コンテナに自動的に登録されます。
その結果、セキュリティ フィルター チェーンを手動で追加する必要はないと思います。なぜなら、Spring Boot の自動構成マジックにより、これが「うまく機能する」と (間違って?) 期待しているからです。
- アプリケーションコンテキストに FilterChainProxy がないのはなぜですか? 繰り返しますが、AutoConfiguration に対する私の期待は間違っている可能性がありますが、これはコンテキスト構成の一部として構成されると思いました。
アドバイスをよろしくお願いします。
編集
FilterChainProxy が注入されない理由は、構成が次のように設定されているためです。
public void configure(WebSecurity web) { web.debug(true); }
これは実際にはorg.springframework.security.web.debug.DebugFilter
代わりに a を構成します。このデバッグ設定に関係なく、フィルターを取得する方法は次のとおりです。
@Resource(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
private Filter securityFilter;
これを MockMvcBuilder に次のように追加すると:
MockMvcBuilders.webAppContextSetup(webApplicationContext).addFilters(securityFilter)
その後、期待どおりに動作します。
しかし、MockMVC がフィルターを無視する理由がわかりません。これは、テストの結果に影響を与える可能性のあるフィルターで何かが発生する可能性があるため、要求をテストするために重要であると思われるからです。さらに、適切にテストするには、サーブレット コンテキストですべてのフィルターを検索し、それらの優先度/URL マッピングを確立して適切に追加する必要があることを意味します。これはエラーが発生しやすく、不要なようです。