J'ai peu de code de travail pour configurer MockMVc
de différentes manières avec le nouveau Spring Boot 1.4 @WebMvcTest
. Je comprends l'approche standaloneSetup. Ce que je veux savoir, c'est la différence entre la configuration de MockMvc
à WebApplicationContext
et le câblage automatique MockMvc
.
Extrait de code 1: MockMvc via 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();
}
}
Selon la documentation de l'API WebMvcTest
, Par défaut, les tests annotés avec @WebMvcTest configureront également automatiquement Spring Security et MockMvc . Donc, je m'attendais à un code d'état 401 non autorisé ici, mais le test réussit avec un code d'état 200.
Ensuite, j'ai essayé le câblage automatique MockMvc
, mais le test échoue avec le code d'état 401 non autorisé, sauf si j'ajoute @AutoConfigureMockMvc(secure=false)
ou met à jour l'annotation @WebMvcTest
Pour désactiver la sécurité:
@WebMvcTest(controllers = IndexController.class, secure = false)
Voici le code qui passe UNIQUEMENT APRÈS avoir désactivé explicitement la sécurité.
Extrait de code 2: MockMvc via le câblage automatique
@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();
}
}
Mes questions sont donc:
Pourquoi l'extrait de code 1 n'a pas signalé d'erreur de code d'état 401 non autorisé lors du câblage automatique MockMvc
. Réitérant également ce que dit le document officiel Par défaut, les tests annotés avec @WebMvcTest configureront également automatiquement Spring Security et MockMvc. Mais, dans ce cas, il apparaît @WebMvcTest
N'a rien à voir avec la configuration automatique de Spring Security (car l'extrait de code 1 passe sans erreur 401). Cela revient finalement à la façon dont j'ai configuré le MockMvc
. Ai-je raison ici?
Quelles sont les différences/objectifs entre/des deux approches?
En quoi la désactivation de la sécurité via @AutoConfigureMockMvc(secure=false)
diffère de celle effectuée via @WebMvcTest(controllers = IndexController.class, secure = false)
. Laquelle est l'approche préférée ou quand (ou où) les utiliser?
Je rencontre également un problème similaire. @WebMvcTest configure automatiquement Spring Security avec l'authentification de base, mais j'ai une classe WebSecurityConfig qui étend WebSecurityConfigurerAdapter. Dans cette classe, j'ai désactivé l'authentification de base et configuré la sécurité de la base de jetons. Cela signifie que la classe WebSecurityConfig n'est pas utilisée pour configurer Spring Security.
Pour résoudre le problème, j'ai ajouté @ContextConfiguration à ma classe de test unitaire et ajouté des simulations de dépendances de la 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")));
}
}
Selon ce problème dans github
https://github.com/spring-projects/spring-boot/issues/5476
@WebMvcTest configure automatiquement par défaut, une authentification de base lorsque spring-security-test est dans le chemin de classe
Répondre à vos questions:
Par défaut, les tests annotés avec @WebMvcTest configurent également automatiquement Spring Security et MockMvc (incluent la prise en charge de HtmlUnit WebClient et Selenium WebDriver). Pour un contrôle plus fin de MockMVC, l'annotation @AutoConfigureMockMvc peut être utilisée.
Je ne suis pas sûr que ce soit directement lié, mais il y a un bug exceptionnel où, si vous utilisez Spring Boot et @WebMvcTest
, votre personnalisé @EnableWebSecurity
La classe de configuration sera ignorée. Quelques solutions de contournement sont mentionnées dans le rapport de bogue. J'utilise:
@WebMvcTest(includeFilters = @Filter(classes = EnableWebSecurity.class))