【发布时间】:2017-07-08 18:00:15
【问题描述】:
我正在开发一个具有一定数量控制器的 Spring Boot MVC 应用程序。 我的根控制器是:
@Controller
@RequestMapping("/")
public class RootController {
@GetMapping
public String showStartPage() {
log.info("GET: Show home page");
return "index";
}
}
我已经成功地为控制器实现了 MVC 测试。我的 RootController 的测试是:
@RunWith(SpringRunner.class)
@WebMvcTest(RootController.class)
public class RootControllerMvcTest {
@Autowired
private MockMvc mvc;
@Test
public void testRoot() throws Exception {
mvc.perform(get("/").accept(MediaType.TEXT_HTML))
.andExpect(status().isOk())
.andExpect(view().name("index"));
}
}
问题:
但是,当我介绍 Spring Security 身份验证和授权时,所有 mvc 控制器测试都失败了。根控制器测试的断言错误是:
java.lang.AssertionError: Status
Expected :200
Actual :401
我的安全配置是:
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/fonts/*").permitAll()
.antMatchers("/user/**").hasAuthority("ADMIN")
.anyRequest().fullyAuthenticated()
.and()
.formLogin()
.loginPage("/login")
.failureUrl("/login?error")
.usernameParameter("email")
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
.deleteCookies("remember-me")
.logoutSuccessUrl("/")
.permitAll()
.and()
.rememberMe();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(new BCryptPasswordEncoder());
}
}
解决方案:
然后,我设法解决了这个问题:
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class RootControllerMvcTest {
...
}
在这种情况下,我的测试会加载整个应用程序上下文。
我的问题是:
- 如何将我的 mvc 测试与身份验证和授权过程分开,只测试控制器的逻辑?
- 测试身份验证和授权实现的最佳实践是什么?我是否必须为此使用@SpringBootTest?
- 单独测试我的控制器和安全逻辑是否是一个好的决定?
谢谢。
【问题讨论】:
-
谢谢。这是一个有用的链接。但首先,我想弄清楚是否可以使用 MockMvc 而完全不使用 Spring Security 来测试我的控制器。
标签: java spring-mvc spring-boot spring-security spring-test-mvc