Я учусь тестировать свои приложения SpringBoot.
Прямо сейчас я пытаюсь учиться, создавая тест для существующего рабочего проекта.
Я начал с моего 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;
}
}
А это мой тест:
@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"));
}
}
И я думаю, что релевантная часть моего 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");
}
И AUTHORITY_ADMIN является окончательным статическим определением "ADMIN".
Что я не могу понять из-за недостатка опыта, так это результаты моих тестов.
- Если я удаляю @ WithMockUser , я получаю 401, как и ожидалось
- Если я использую @ WithMockUser с ЛЮБЫМИ полномочиями, отличными от «ADMIN», я получу 403, что также будет ожидаемым ответом
- И, наконец, если я использую @ WithMockUser с полномочиями "ADMIN", тогда я получу 404
Как уже говорилось, мое приложение работает, и я могу получить доступ к / admin / home только в том случае, если вы вошли как ADMIN.
UPDATE
Запуск другого подобного теста работает нормально, но для его загрузки требуется ПОЛНОЕ приложение SpringBoot. Я думаю, что это будет интеграционный тест, и я хочу проверить только контроллер "один". Только фрагмент с использованием @ 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"));
}
}
ОБНОВЛЕНИЕ 2
Я делаю это, изменяя @ ContextConfiguration (classes = MyOwnProperties.class) для @ Import
Итак, теперь мой тест выглядит так:
@RunWith(SpringRunner.class)
@WebMvcTest(AdminHomeController.class)
@Import({SecurityConfigurationGlobal.class, MyOwnProperties.class})
public class AdminHomeControllerUnitTest {
....... Same as before
}
Я счастлив, потому что тест пройден, но может кто-нибудь объяснить мне, почему? В другом посте SO я читал, что для использования моих собственных файлов свойств, помеченных @ConfigurationProperties, мне нужно использовать аннотацию @ContextConfiguration.