Cześć,
Piszę w sprawie problemu z testami dla prostej aplikacji na SpringBoot ze Spring security:
Oto test:
package pl.group7.controller;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import pl.group7.DummyObjects;
import pl.group7.model.User;
import pl.group7.service.UserService;
import static org.mockito.BDDMockito.given;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/**
* Created by allst on 05.05.2017.
*/
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class UserControllerTest {
@Autowired
WebApplicationContext webContext;
@MockBean
UserService userService;
MockMvc mockMvc;
private User user = DummyObjects.getDummyUser();
public static String asJsonString(final Object obj) {
try {
return new ObjectMapper().writeValueAsString(obj);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static User getObjectFromJson(final String json){
try{
return new ObjectMapper().readValue(json, User.class);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Before
@WithMockUser(username = "admin",authorities = {"SU","ADMIN"})
public void setUp() throws Exception {
mockMvc = MockMvcBuilders
.webAppContextSetup(webContext)
.apply(springSecurity())
.build();
}
@Test
@WithMockUser(username = "admin",authorities = {"SU","ADMIN"})
public void shouldAddUser() throws Exception {
given(this.userService.save(user)).willReturn(user);
mockMvc.perform(post("/user")
.content(asJsonString(user))
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.with(csrf().asHeader()))
.andExpect(status().is(200));
}
@Test
@WithMockUser(username = "admin",authorities = {"SU","ADMIN"})
public void removeUser() throws Exception {
mockMvc.perform(delete("/user/1")
.with(csrf().asHeader()))
.andExpect(status().is(200));
}
A to konfiguracja security:
package pl.group7.configuration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.security.web.csrf.CsrfFilter;
import pl.group7.security.CsrfTokenResponseHeaderBindingFilter;
import pl.group7.security.RESTAuthenticationFailureHandler;
import pl.group7.security.RESTAuthenticationSuccessHandler;
import pl.group7.service.CustomUserDetailsService;
/**
* created by : Dominik 12.03.2017
* */
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
CustomUserDetailsService userDetailsService;
@Autowired
private RESTAuthenticationFailureHandler authenticationFailureHandler;
@Autowired
private RESTAuthenticationSuccessHandler authenticationSuccessHandler;
@Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("user").authorities("MAKE_ORDER");
auth.inMemoryAuthentication().withUser("admin").password("admin").authorities("SU");
auth.userDetailsService(userDetailsService);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/api/**").hasAuthority("SU")
.antMatchers(HttpMethod.POST, "/api/user").permitAll()
.antMatchers(HttpMethod.PUT, "/api/user").authenticated()
.antMatchers(HttpMethod.DELETE,"api/user/**").authenticated()
.and().formLogin().successHandler(authenticationSuccessHandler)
.and().formLogin().failureHandler(authenticationFailureHandler);
http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and().addFilterAfter(new CsrfTokenResponseHeaderBindingFilter(), CsrfFilter.class);
// http.csrf().disable();
}
}
I przy odpalaniu testu dostaje kod http 404. Wzorowałem się na http://docs.spring.io/spring-security/site/docs/current/reference/html/test-method.html .
Macie jakieś pomysły dotyczące dlaczego nie mogę się dostać do kontrollera skoro daje mu csrf jak i przekazuje ze jestem zalogowany jako admin z odpowiednimi prawami.
pozdrawiam