[英]Spring Boot @WebMvcTest returns 404 if success login
I'm learning how to Test my SpringBoot Apps.我正在学习如何测试我的 SpringBoot 应用程序。
Right now I'm trying to learn by creating test for an existing working project.现在我正在尝试通过为现有工作项目创建测试来学习。
I started with my AdminHomeController that manages the Home when admins login:我从管理员登录时管理主页的AdminHomeController开始:
@Controller
@RequestMapping("/admin/home")
public class AdminHomeController {
private UsuarioService usuarioService;
@Autowired
public AdminHomeController(UsuarioService usuarioService) {
this.usuarioService = usuarioService;
}
@RequestMapping(value={"", "/"}, method = RequestMethod.GET)
public ModelAndView admin_home(){
ModelAndView modelAndView = new ModelAndView();
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
Usuario loggedUser = usuarioService.findUsuarioByUsername(auth.getName());
modelAndView.addObject("userFullName", loggedUser.getNombre() + " " + loggedUser.getApellido());
modelAndView.addObject("userGravatar", Utils.getGravatarImageLink(loggedUser.getEmail()));
modelAndView.addObject("totalUsuarios", usuarioService.getUsuariosCount());
modelAndView.setViewName("admin/home");
return modelAndView;
}
}
And this is my test:这是我的测试:
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = MyOwnProperties.class)
@WebMvcTest(AdminHomeController.class)
@Import(SecurityConfigurationGlobal.class)
public class AdminHomeControllerUnitTest {
@Autowired
private MockMvc mockMvc;
@MockBean
UsuarioService usuarioService;
@Autowired
MyOwnProperties myOwnProperties;
@MockBean
FacebookProfileService facebookProfileService;
@MockBean
MobileDeviceService mobileDeviceService;
@MockBean
PasswordEncoder passwordEncoder;
@MockBean
CustomAuthenticationProvider customAuthenticationProvider;
@Test
@WithMockUser(username = "user1", password = "pwd", authorities = "ADMIN")
public void shouldAllowAdminAccess() throws Exception{
when(usuarioService.findUsuarioByUsername("user1")).thenReturn(new Usuario());
mockMvc.perform(get("/admin/home"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(view().name("admin/home"));
}
}
And I think that the relevan part of my SecurityConfig would be:我认为我的 SecurityConfig 的相关部分是:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.
authorizeRequests()
.antMatchers("/", "/login", "/error/**", "/home").permitAll()
.antMatchers(
myOwnProperties.getSecurity().getJwtLoginURL(),
myOwnProperties.getSecurity().getFacebookLoginURL()).permitAll()
.antMatchers("/registration", "/registrationConfirm/**").permitAll()
.antMatchers("/resetPass", "/resetPassConfirm/**", "/updatePass").permitAll()
.antMatchers("/admin/**").hasAuthority(AUTHORITY_ADMIN)
.antMatchers("/user/**").hasAuthority(AUTHORITY_USER)
.anyRequest().authenticated()
.and()
.csrf().disable()
.formLogin()
.loginPage("/login")
.failureUrl("/login?error=true")
.successHandler(new CustomUrlAuthenticationSuccessHandler())
.usernameParameter("username")
.passwordParameter("password")
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.and()
.exceptionHandling().accessDeniedPage("/403");
}
And AUTHORITY_ADMIN is a static final definition of "ADMIN".而AUTHORITY_ADMIN是“ADMIN”的静态最终定义。
What I can not understand due to my lack of experience are my test results.由于我缺乏经验,我无法理解的是我的测试结果。
As said, my app is working and I can only access /admin/home if logged in as ADMIN.如前所述,我的应用程序正在运行,如果以 ADMIN 身份登录,我只能访问 /admin/home。
Running this other similiar test works fine, but this one requieres the FULL SpringBoot app to load.运行这个其他类似的测试工作正常,但这个需要加载完整的 SpringBoot 应用程序。 I think it would be an integration test and I only want to test the controller "alone".
我认为这将是一个集成测试,我只想“单独”测试控制器。 Only a slice using @WebMvcTest
只有一个切片使用@WebMvcTest
@SpringBootTest
@AutoConfigureMockMvc
public class AdminHomeControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UsuarioService usuarioService;
@Test
@WithMockUser(username = "user1", password = "pwd", authorities = "ADMIN")
public void shouldAllowAdminAccess() throws Exception{
when(usuarioService.findUsuarioByUsername(anyString())).thenReturn(new Usuario());
mockMvc.perform(get("/admin/home"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(view().name("admin/home"));
}
}
I make it pass by changing the @ContextConfiguration(classes = MyOwnProperties.class) for a @Import我通过将@ContextConfiguration(classes = MyOwnProperties.class)更改为@Import使其通过
So now my test looks like:所以现在我的测试看起来像:
@RunWith(SpringRunner.class)
@WebMvcTest(AdminHomeController.class)
@Import({SecurityConfigurationGlobal.class, MyOwnProperties.class})
public class AdminHomeControllerUnitTest {
....... Same as before
}
I'm happy because the test pass but can someone explain me why?我很高兴,因为测试通过了,但有人能解释一下为什么吗? I was reading in other SO post that to use my own custom properties files annotated with @ConfigurationProperties I need to use @ContextConfiguration annotation.
我在其他 SO 帖子中读到,要使用我自己的带有 @ConfigurationProperties 注释的自定义属性文件,我需要使用 @ContextConfiguration 注释。
The solution to my problem was to replace @ContextConfiguration(classes = MyOwnProperties.class) for a @Import我的问题的解决方案是将@ContextConfiguration(classes = MyOwnProperties.class)替换为@Import
So it would become:所以它会变成:
@RunWith(SpringRunner.class)
@WebMvcTest(AdminHomeController.class)
@Import({SecurityConfigurationGlobal.class, MyOwnProperties.class})
public class AdminHomeControllerUnitTest {
....... Same as before
}
I've now migrated my code base to Spring Boot 2.4.1
and this test start failing again.我现在已将我的代码库迁移到
Spring Boot 2.4.1
,此测试再次开始失败。 After trial and error, now the @Import need to be replaced with @ContextConfiguration .经过反复试验,现在需要将@Import替换为@ContextConfiguration 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.