我使用新的Spring Boot 1.4 MockMVc
以不同的方式设置@WebMvcTest
的工作代码很少。我理解standaloneSetup方法。我想知道的是设置MockMvc
到WebApplicationContext
和自动装配MockMvc
之间的区别。
代码段1:通过WebApplicationContext设置MockMvc
@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();
}
}
根据WebMvcTest
API文档,默认情况下,使用@WebMvcTest注释的测试也会自动配置Spring Security和MockMvc 。所以,我希望这里有一个401 Unauthorized状态代码,但测试通过200状态代码。
接下来,我尝试了自动连接MockMvc
,但测试失败并显示401 Unauthorized状态代码,除非我添加@AutoConfigureMockMvc(secure=false)
或更新@WebMvcTest
注释以禁用安全性:
@WebMvcTest(controllers = IndexController.class, secure = false)
以下是仅在明确禁用安全性后才传递的代码。
代码段2:通过自动装配模拟MockMvc
@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();
}
}
所以我的问题是:
为什么没有代码段1在自动连接MockMvc
时报告401未授权状态代码错误。同样重申官方文档所说的默认情况下,使用@WebMvcTest注释的测试也会自动配置Spring Security和MockMvc。但是,在这种情况下,它显示@WebMvcTest
与auto无关 - 配置Spring安全性(因为代码片段1通过而没有任何401错误)。它最终归结为我如何设置MockMvc
。我在这里纠正吗?
两种方法之间的差异/目标是什么?
如何通过@AutoConfigureMockMvc(secure=false)
禁用安全性与执行@WebMvcTest(controllers = IndexController.class, secure = false)
的方式不同。哪一个是接近的,或者何时(或在何处)使用它们?
答案 0 :(得分:8)
我也遇到过类似的问题。 @WebMvcTest auto使用基本身份验证配置Spring Security,但我有一个扩展WebSecurityConfigurerAdapter的WebSecurityConfig类。在这个类中,我禁用了基本身份验证和配置的令牌库安全性。这意味着WebSecurityConfig类不用于配置Spring Security。
为了解决这个问题,我将@ContextConfiguration添加到我的单元测试类中,并添加了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")));
}
}
答案 1 :(得分:6)
根据github中的这个问题
https://github.com/spring-projects/spring-boot/issues/5476
@WebMvcTest默认情况下自动配置,当spring-security-test在类路径中时是一个基本的auth
回答你的问题:
默认情况下,使用@WebMvcTest注释的测试也会自动配置 Spring Security和MockMvc(包括对HtmlUnit WebClient的支持 和Selenium WebDriver)。对于MockMVC的更精细控制 可以使用@AutoConfigureMockMvc注释。
答案 2 :(得分:3)
我不确定这是否直接相关,但有一个outstanding bug,如果使用spring boot和@WebMvcTest
,您的自定义@EnableWebSecurity
配置类将被忽略。错误报告中提到了几种解决方法。我正在使用:
@WebMvcTest(includeFilters = @Filter(classes = EnableWebSecurity.class))
答案 3 :(得分:0)
我不知道这是否正确,但我可以使用下面的方法禁用配置类
@WebMvcTest(ProductController.class)
@ContextConfiguration(classes = ProductController.class)
public class ProductControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private ProductService productServiceMock;