Dav*_*vid 14 spring-security spring-test spring-test-mvc spring-boot mockmvc
我在使用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());
}
}
Run Code Online (Sandbox Code Playgroud)
这导致HTTP 200而不是401.我启用了组件扫描和自动配置,并在我的SecuityConfiguration类中配置了spring安全性,如下所示:
@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
}
}
Run Code Online (Sandbox Code Playgroud)
如果我使用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
).
我有两个问题:
上下文中定义的任何{@link Servlet}或{@link Filter} bean将自动注册到嵌入式Servlet容器中
因此,我不希望手动添加安全过滤器链,因为我(错误地?)由于Spring Boot中的自动配置魔法而期望它"正常工作"?
提前感谢任何建议.
FilterChainProxy没有被注入的原因是因为我将配置设置为
public void configure(WebSecurity web){web.debug(true); }
这实际上配置了一个org.springframework.security.web.debug.DebugFilter
.无论此调试设置如何,我现在设法获得过滤器的方式如下:
@Resource(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
private Filter securityFilter;
Run Code Online (Sandbox Code Playgroud)
如果我将它添加到MockMvcBuilder,如下所示:
MockMvcBuilders.webAppContextSetup(webApplicationContext).addFilters(securityFilter)
Run Code Online (Sandbox Code Playgroud)
那么它确实按预期工作.
但是,我不明白为什么MockMVC会忽略过滤器,因为这对于测试请求似乎很重要,因为在过滤器中可能会发生任何可能影响测试结果的事情.此外,这意味着要正确测试我需要在servlet上下文中查找所有过滤器并建立它们的优先级/ url映射并适当地添加它们.这似乎容易出错且不必要.
我同意Mock MVC可能更多用于测试控制器中的Spring MVC和自定义代码,正如@ dave-syer所评论的那样.因此,如果想要同时使用您的自定义控制器代码测试spring MVC基础结构(映射到URL的控制器的正确性;输入和输出对象的映射和验证;标准控制器;您的控制器)而不利用Servlet容器部分堆栈,MockMVC就在你身边.
但是MockMVC也有添加过滤器的方法,因此它的设计可以在所描述的测试类型中使用过滤器.有时,过滤器可能对控制器内的代码起作用,而MockMVC则无法测试.
考虑到所有这些理论,我试图模仿我的测试的Boot行为,其中过滤器将以Spring Boot方式设置,并通过我的测试获取以与MockVMC一起使用.这是我最终使用的片段.它肯定可以被更强大地模仿Boot行为并提取到一些自定义MockMVCBuilder.
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setUp() {
Collection<Filter> filterCollection = wac.getBeansOfType(Filter.class).values();
Filter[] filters = filterCollection.toArray(new Filter[filterCollection.size()]);
mockMvc = MockMvcBuilders.webAppContextSetup(wac).addFilters(filters).build();
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
12244 次 |
最近记录: |