2015-04-17 16 views
7

Ho un'applicazione di avvio a molla che richiede l'accesso per alcune azioni. Sto provando a testarli usando MockMvc, ma non sembra funzionare. Continuo a ricevere una risposta HTTP con stato 403 (vietato). Probabilmente c'è qualcosa di sbagliato nella parte di autenticazione.Esegui test di unità su controller che richiedono l'autenticazione

Ho provato a seguire il documentation, ma non sono riuscito a farlo funzionare.

Questo è il mio codice di prova corrente:

@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"); 
    } 
} 

Scusate se mi manca qualcosa di ovvio. Questa è la mia prima esperienza con lo stivale a molla.

+1

Sono curioso del metodo 'springSecurity()'. Potresti mostrare il corpo del metodo di quel metodo? –

+1

Il metodo springSecurity() è fornito da Spring Security. Aggiunge il filtro springSecurityFilterChain e garantisce che il supporto di test sia integrato nel filtro. –

risposta

21

È necessario specificare quale utente si desidera eseguire il test come. Hai alcune opzioni (ogni opzione è un link alla documentazione dettagliata):

@WithMockUser

Questa opzione consente di creare un utente falso (cioè l'utente non ha bisogno di esistere in un archivio dati). Il problema con questo approccio è che se la tua applicazione si basa su un'implementazione utente personalizzata potresti ottenere eccezioni di cast di classe. Se non si restituisce un tipo personalizzato da un UserDetailsService personalizzato, questa soluzione dovrebbe funzionare correttamente.

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

@WithUserDetails

Se implementato un'UserDetailsService personalizzato che restituisce un'implementazione personalizzata di UserDetails, questa soluzione può funzionare per voi.

Affinché funzioni, è necessario esporre un UserDetailsService come bean e l'utente deve esistere. Per esempio:

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

@WithSecurityContext

Questo è il meglio dei due mondi, ma richiede un po 'di configurazione aggiuntiva. Se hai un UserDetailsService personalizzato che restituisce un'implementazione personalizzata di UserDetails e NON vuoi che l'utente debba necessariamente esistere, puoi utilizzare questo metodo. Ti consentirò di leggere la documentazione su questa configurazione poiché è un po 'più lunga e ben documentata.

Using a RequestPostProcessor

Se le annotazioni non sono la vostra passione è possibile utilizzare un RequestPostProcessor. Ad esempio:

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 qualche idea ??? – Gurkha

Problemi correlati