2015-04-17 4 views
7

Ich habe eine Spring-Boot-Anwendung, die für einige Aktionen eine Anmeldung erfordert. Ich versuche, sie mit MockMvc zu testen, aber es scheint nicht zu funktionieren. Ich bekomme immer eine HTTP-Antwort mit Status 403 (verboten). Wahrscheinlich stimmt etwas mit dem Authentifizierungsteil nicht.Führen Sie Unit-Tests auf Controllern durch, die eine Authentifizierung erfordern

Ich habe versucht, die documentation zu folgen, aber ich konnte es nicht funktionieren.

Dies ist mein aktueller Testcode:

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

Sorry, wenn ich etwas offensichtlich fehle. Dies ist meine erste Erfahrung mit Spring Boot.

+1

Ich bin neugierig auf Ihre 'springSecurity()' Methode. Könnten Sie bitte den Methodenkörper dieser Methode zeigen? –

+1

Die Methode SpringSecurity() wird von Spring Security bereitgestellt. Es fügt den springSecurityFilterChain-Filter hinzu und stellt sicher, dass die Testunterstützung in den Filter integriert ist. –

Antwort

21

Sie müssen angeben, für welchen Benutzer Sie den Test ausführen möchten. Sie haben ein paar Optionen (jede Option ist ein Link auf die ausführliche Dokumentation):

@WithMockUser

Diese Option wird einen gefälschten Benutzer erstellen (das heißt der Benutzer muss nicht in einem Datenspeicher vorhanden ist). Das Problem bei diesem Ansatz besteht darin, dass Sie, wenn Ihre Anwendung auf einer benutzerdefinierten Benutzerimplementierung basiert, Klassenausnahmebedingungen erhalten können. Wenn Sie keinen benutzerdefinierten Typ aus einem benutzerdefinierten UserDetailsService zurückgeben, sollte diese Lösung funktionieren.

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

@WithUserDetails

Wenn Sie eine benutzerdefinierte UserDetailsService implementiert, die eine benutzerdefinierte Implementierung von Userdetails zurückgibt, kann diese Lösung für Sie arbeiten.

Damit es funktioniert, müssen Sie einen UserDetailsService als Bean verfügbar machen und der Benutzer muss vorhanden sein. Zum Beispiel:

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

@WithSecurityContext

Dies ist das Beste aus beiden Welten, sondern erfordert eine wenig zusätzliche Einrichtung. Wenn Sie über einen benutzerdefinierten UserDetailsService verfügen, der eine benutzerdefinierte Implementierung von UserDetails zurückgibt und der Benutzer NICHT unbedingt existieren muss, können Sie diese Methode verwenden. Ich lasse Sie die Dokumentation zu diesem Setup lesen, da es etwas länger und gut dokumentiert ist.

Using a RequestPostProcessor

Wenn Anmerkungen nicht Ihr Ding sind, können Sie einen RequestPostProcessor verwenden. Zum Beispiel:

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 keine Idee ??? – Gurkha

Verwandte Themen