2015-04-17 21 views
7

Mam aplikację rozruchową, która wymaga logowania do niektórych działań. Próbuję przetestować je za pomocą MockMvc, ale nie wydaje się działać. Ciągle otrzymuję odpowiedź HTTP o statusie 403 (zabronione). Prawdopodobnie coś jest nie tak z częścią uwierzytelniania.Uruchamiaj testy jednostek na kontrolerach wymagających uwierzytelniania.

Próbowałem podążać za documentation, ale nie udało mi się uruchomić.

To jest mój aktualny kod do testowania:

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = {Application.class}) 
@WebIntegrationTest("server.port = 8093") 
public class PasswordChangeTests { 
    @Autowired 
    private EmbeddedWebApplicationContext webApplicationContext; 

    @Autowired 
    private UserRepository userRepository; 

    private MockMvc mockMvc; 

    @Before 
    public void setUp() throws Exception { 
     this.mockMvc = MockMvcBuilders 
       .webAppContextSetup(webApplicationContext) 
       .apply(springSecurity()) 
       .build(); 
    } 

    @Test 
    public void changePasswordWorks() throws Exception { 
     // Send password change request 
     PasswordChangeRepresentation passwordChange = new PasswordChangeRepresentation(DefaultUsers.Admin.getPassword(), "12345678"); 
     mockMvc.perform(MockMvcRequestBuilders.request(HttpMethod.POST, "/password/change") 
       .content(new ObjectMapper().writeValueAsString(passwordChange)) 
       .contentType(MediaType.APPLICATION_JSON) 
       .accept(MediaType.APPLICATION_JSON)) 
       .andExpect(status().isOk()); 

     // Check that the password has been changed 
     User user = this.userRepository.findByUsername(DefaultUsers.Admin.getEmail()); 
     Assert.assertEquals(user.getPassword(), "12345678"); 
    } 
} 

Przepraszam, jeśli jestem brakujące coś oczywistego. To moje pierwsze doświadczenie z wiosennym zyskiem.

+1

Ciekawi mnie twoja metoda 'springSecurity()'. Czy mógłbyś pokazać metodę metody tej metody? –

+1

Metoda springSecurity() jest zapewniana przez Spring Security. Dodaje filtr springSecurityFilterChain i zapewnia zintegrowanie obsługi testowej z filtrem. –

Odpowiedz

21

Należy określić, który użytkownik, na którym ma zostać wykonany test. Masz kilka opcji (każda opcja jest link do szczegółowej dokumentacji):

@WithMockUser

Ta opcja spowoduje utworzenie Fake (tj użytkownik nie musi istnieć w magazynie danych). Problem z tym podejściem polega na tym, że jeśli aplikacja korzysta z niestandardowej implementacji użytkownika, można uzyskać wyjątki od klasy. Jeśli nie zwrócisz niestandardowego typu z niestandardowej usługi UserDetailsService, to powinno to działać dobrze.

@Test 
@WithMockUser(username="admin",roles={"USER","ADMIN"}) 
public void changePasswordWorks() throws Exception { 

@WithUserDetails

Jeśli wdrożone niestandardowego UserDetailsService zwracającą niestandardową implementację UserDetails, to rozwiązanie może pracować dla Ciebie.

Aby to działało, należy ujawnić UserDetailsService jako Bean, a użytkownik musi istnieć. Na przykład:

@Test 
@WithUserDetails("admin") 
public void changePasswordWorks() throws Exception { 

@WithSecurityContext

To najlepsze z obu światów, ale wymaga trochę dodatkowej konfiguracji. Jeśli masz niestandardową UserDetailsService zwracającą niestandardową implementację UserDetails i NIE chcesz, aby użytkownik musiał istnieć, możesz użyć tej metody. Pozwolę ci przeczytać dokumentację tej instalacji, ponieważ jest ona nieco bardziej długa i dobrze udokumentowana.

Using a RequestPostProcessor

Jeśli adnotacje nie są twoje rzeczy można użyć RequestPostProcessor. Na przykład:

import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*; 

... 

@Test 
public void changePasswordWorks() throws Exception { 
    // Send password change request 
    PasswordChangeRepresentation passwordChange = new PasswordChangeRepresentation(DefaultUsers.Admin.getPassword(), "12345678"); 
    mockMvc.perform(MockMvcRequestBuilders.request(HttpMethod.POST, "/password/change") 

      // ADD this line 
      .with(user("admin").roles("USER","ADMIN")) 

      .content(new ObjectMapper().writeValueAsString(passwordChange)) 
      .contentType(MediaType.APPLICATION_JSON) 
      .accept(MediaType.APPLICATION_JSON)) 
      .andExpect(status().isOk()); 

    // Check that the password has been changed 
    User user = this.userRepository.findByUsername(DefaultUsers.Admin.getEmail()); 
    Assert.assertEquals(user.getPassword(), "12345678"); 
} 
+0

http://stackoverflow.com/questions/43073515/test-spring-mvc-controller-with-preauthorize-giving-403-access-denied jakiś pomysł ??? – Gurkha