2016-07-03 72 views
8

Ho pochi codici funzionanti per impostare MockMVc in diversi modi con il nuovo Spring Boot 1.4 @WebMvcTest. Comprendo l'approccio standaloneSetup. Quello che voglio sapere è la differenza tra la configurazione di MockMvc tramite WebApplicationContext e l'autowiring MockMvc.Configurazione di MockMvc con @WebMvcTest in Spring Boot 1.4 Test MVC

Snippet di codice 1: MockMvc attraverso WebApplicationContext Setup

@RunWith(SpringRunner.class) 
@WebMvcTest(controllers = ProductController.class) 
public class ProductControllerTest { 

private MockMvc mockMvc; 

@Autowired 
private WebApplicationContext webApplicationContext; 

@MockBean 
private ProductService productServiceMock; 

@Before 
public void setUp() { 
    mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); 
} 

@Test 
public void testShowProduct() throws Exception {  

    Product product1 = new Product(); 
    /*Code to initialize product1*/ 

    when(productServiceMock.getProductById(1)).thenReturn(product1); 

    MvcResult result = mockMvc.perform(get("/product/{id}/", 1)) 
      .andExpect(status().isOk()) 
      /*Other expectations*/ 
      .andReturn(); 
    } 
} 

Come da WebMvcTest documentazione delle API, Per impostazione predefinita, le prove annotate con @WebMvcTest anche auto-configurare Primavera di sicurezza e MockMvc. Quindi, mi aspettavo un codice di stato 401 non autorizzato qui, ma il test passa con un codice di stato 200.

Successivamente, ho cercato di cablaggio auto MockMvc, ma il test non riesce con 401 codice di stato non autorizzato, a meno che non aggiungo @AutoConfigureMockMvc(secure=false) o aggiornare il @WebMvcTest annotazioni per disattivare la protezione:

@WebMvcTest(controllers = IndexController.class, secure = false) 


seguito è riportato il codice che passa SOLO DOPO disattivare esplicitamente la sicurezza.

Snippet di codice 2: MockMvc attraverso autowiring

@RunWith(SpringRunner.class) 
@WebMvcTest(controllers = ProductController.class) 
@AutoConfigureMockMvc(secure=false) 
public class ProductControllerTest { 
@Autowired 
private MockMvc mockMvc; 
@Autowired 
private WebApplicationContext webApplicationContext; 
@MockBean 
private ProductService productServiceMock; 

@Test 
public void testShowProduct() throws Exception {  

    Product product1 = new Product(); 
    /*Code to initialize product1*/ 

    when(productServiceMock.getProductById(1)).thenReturn(product1); 

    MvcResult result = mockMvc.perform(get("/product/{id}/", 1)) 
      .andExpect(status().isOk()) 
      /*Other expectations*/ 
      .andReturn(); 
    } 
} 

Quindi le mie domande sono:

  1. Perché non Codice snippet 1 rapporto aa 401 errore di codice di stato non autorizzato durante il cablaggio auto MockMvc fatto . Ripetendo anche ciò che dice il documento ufficiale Per impostazione predefinita, i test annotati con @WebMvcTest configurano automaticamente anche Spring Security e MockMvc. Ma, in questo caso, appare @WebMvcTest non ha nulla a che fare con la configurazione automatica di Spring Security (perché il frammento di codice 1 passa senza errori 401). Finalmente si riduce a come ho impostato il MockMvc. Sono corretto qui?

  2. Quali sono le differenze/obiettivi tra/di entrambi gli approcci?

  3. In che modo la disattivazione della sicurezza tramite @AutoConfigureMockMvc(secure=false) differisce dal modo di eseguire fino a @WebMvcTest(controllers = IndexController.class, secure = false). Quale è l'approccio preferito o quando (o dove) usarli?

risposta

6

Mi sono imbattuto anche in un problema simile. @WebMvcTest configura automaticamente Spring Security con l'autenticazione di base, ma ho una classe WebSecurityConfig che estende WebSecurityConfigurerAdapter. In questa classe ho disabilitato l'autenticazione di base e la sicurezza della base di token configurata. Ciò significa che la classe WebSecurityConfig non viene utilizzata per configurare Spring Security.

Per risolvere il problema, ho aggiunto @ContextConfiguration alla classe di test dell'unità e aggiunto mock di dipendenze della classe WebSecurityConfig.

@RunWith(SpringRunner.class) 
@WebMvcTest(controllers = CategoryRestService.class) 
@ContextConfiguration(classes={MjApplication.class, WebSecurityConfig.class}) 
public class CategoryRestServiceTest { 

    @MockBean 
    private CategoryRepository repository; 

    @MockBean 
    CurrentUserDetailsService currentUserDetailsService; 

    @MockBean 
    TokenAuthProvider tokenAuthProvider; 

    @Autowired 
    MockMvc mockMvc; 

    private MediaType contentType = new MediaType(MediaType.APPLICATION_JSON.getType(), 
      MediaType.APPLICATION_JSON.getSubtype(), Charset.forName("utf8")); 


    @Test 
    public void getCategories() throws Exception { 
     Category category1 = new Category(); 
     category1.setName("Test Category 1"); 
     category1.setId(1L); 
     Category category2 = new Category(); 
     category2.setName("Test Category 2"); 
     category2.setId(2L); 
     List<Category> categoryList = new ArrayList<Category>(); 
     categoryList.add(category1); 
     categoryList.add(category2); 
     given(this.repository.findAll()) 
     .willReturn(categoryList); 
     mockMvc.perform(get("/public/rest/category")) 
     .andExpect(status().isOk()) 
     .andExpect(content().contentType(contentType)) 
     .andExpect(jsonPath("$[0].id", is(1))) 
     .andExpect(jsonPath("$[0].name", is("Test Category 1"))) 
     .andExpect(jsonPath("$[1].id", is(2))) 
     .andExpect(jsonPath("$[1].name", is("Test Category 2"))); 
    } 

} 
6

Secondo questo problema in github

https://github.com/spring-projects/spring-boot/issues/5476

@WebMvcTest auto configura per default, un'autenticazione base quando la primavera-sicurezza-test è nel percorso di classe

Risposte alle domande :

  1. Nel snippet di codice 1, non viene iniettato e MockMvc nella tua classe di test, dovresti aggiungere .apply (springSecurity()) nel builder sul metodo di installazione, quindi spring userebbe la configurazione di base (non la tua configurazione di sicurezza personalizzata se ne hai una)
  2. la stessa cosa, la differenza è che il secondo viene fornito con l'autenticazione di base già nel MockMvc, per questo è necessario utilizzare la sicura = false
  3. Dalla documentazione:

per impostazione predefinita, le prove annotato con @WebMvcTest verrà inoltre configurato automaticamente Spring Security e MockMvc (include il supporto per HtmlUnit WebClient e Selenium WebDriver). Per un controllo più preciso di MockMVC è possibile utilizzare l'annotazione @AutoConfigureMockMvc.

2

io non sono sicuro che questo è direttamente collegata, ma non v'è un outstanding bug in cui, se si utilizza avvio primavera e @WebMvcTest, verrà ignorata la vostra abitudine @EnableWebSecurity classe config. Un paio di soluzioni sono menzionate nella segnalazione di bug. Sto usando:

@WebMvcTest(includeFilters = @Filter(classes = EnableWebSecurity.class))