当前位置: 首页 > 知识库问答 >
问题:

在Spring Boot 1.4 MVC测试中使用@WebMvcTest设置MockMvc

赵景曜
2023-03-14

在新的Spring Boot 1.4 < code > @ WebMvcTest 中,我只有很少的工作代码来以不同的方式设置< code>MockMVc。我理解独立安装的方法。我想知道的是通过< code > WebApplicationContext 和通过自动绑定< code>MockMvc来设置< code>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();
  }
}

根据WebMvcTestAPI留档,默认情况下,使用@WebMvcTest注释的测试也将自动配置Spring Security和MockMvc。所以,我在这里期望一个401未授权状态代码,但测试以200状态代码通过。

接下来,我尝试自动连接MockMvc,但测试失败,出现401个未经授权的状态代码,除非我添加@AutoConfigureMockMvc(secure=false)或更新@WebMvcTestannotation以禁用安全性:

@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没有报告401未授权状态代码错误,而自动布线MockMvc报告了。同样重申了官方文档默认所说的,带有@WebMvcTest注释的测试也将自动配置Spring Security和MockMvc。但是,在这种情况下,@WebMvcTest似乎与自动配置Spring Security性无关(因为代码段1没有任何401错误)。它最终归结为如何设置<code>MockMvc</code>。我说得对吗?

    这两种方法的区别/目标是什么?

    通过< code > @ AutoConfigureMockMvc(secure=false)禁用安全性与通过< code > @ WebMvcTest(controllers = index controller . class,secure = false)禁用安全性有何不同。哪一种是首选方法,或者何时(或何地)使用它们?

  • 共有3个答案

    燕鸿文
    2023-03-14

    我不确定这是否直接相关,但有一个突出的错误,如果使用Spring boot和@WebMvcTest,您的自定义@EnableWebSecurity配置类将被忽略。错误报告中提到了一些解决方法。我正在使用:

    @WebMvcTest(includeFilters = @Filter(classes = EnableWebSecurity.class))
    
    陈功
    2023-03-14

    根据github中的这个问题

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

    @WebMvcTest默认自动配置,当spring-security-test在类路径中时的基本身份验证

    回答您的问题:

      < li >在代码片段1中,您没有在测试类中注入MockMvc,您应该添加。在安装方法的构建器中应用(springSecurity()),这样spring将使用基本配置(不是您的自定义安全配置,如果您有) < li >这两种方法做的事情基本相同,区别在于第二种方法带有MockMvc中已有的基本auth,这就是为什么您必须使用secure=false < li >来自文档:

    默认情况下,使用@WebMvcTest注释的测试还将自动配置Spring Security和MockMvc(包括对HtmlUnit WebClient和Selenium WebDriver的支持)。对于MockMVC的更细粒度的控制,可以使用@AutoConfigreMockMvc注释。

    谈秦斩
    2023-03-14

    我也遇到了类似的问题@WebMvcTest使用基本身份验证自动配置Spring Security,但我有一个扩展<code>WebSecurityConfigureAdapter的<code>WebSecurityConfig在这个类中,我禁用了基本身份验证并配置了令牌基安全性。这意味着<code>WebSecurityConfig<code>类不用于配置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")));
        }
    
    }
    
     类似资料:
    • 将@service添加到控制器后,单元测试失败。该项目是Spring-boot V2.0.1版本。我花了很多时间想找到答案,但没有成功。在我添加@service注释之前,测试工作正常,并且我的服务类在其中有一个存储库。 堆栈跟踪: 2018-04-24 12:57:12.487警告940--[main]O.s.w.cs.GenericWebApplicationContext:上下文初始化过程中遇

    • 我想在中测试我的restendpoint。我用编写了一个测试。 这是我在中的方法 现在,当我运行测试时,我得到一个错误 Spring Boot:v2.1.0.发行版 编辑:它起作用了。我怀念我的中的...我删除了这段代码,现在它起作用了

    • 我有一个Spring Boot应用程序(1.5.10.release),其中包含一个主程序(SpringBootApplication)如下所示: 存储库如下所示: A和B它们本身是JPA注释类。整个应用程序包含对数据库的访问。 此外,我有这样一个服务: XService不是通过@autowire或其他方式使用的(只需要删除它): 因此,我尝试运行AControllerTest,得到以下错误: j

    • 我已经按照这里描述的“测试Spring MVC切片”一节为Spring MVC控制器编写了一个测试类。类如下所示: 当我运行它时,我得到了以下错误: 有人能解释为什么@webmvctest注释对我不起作用吗?

    • 问题内容: 我有这样的环境: 在Mac OS X上运行的PyCharm 在流浪汉实例中的Ubuntu3.4上运行的Python3.4环境 我希望能够使用PyCharm运行/调试测试。到目前为止,我可以做到,但是最近我在测试中添加了selenium,现在我需要在 xvfb-run remote命令中包装python解释器。我尝试添加远程外部工具,但无法使其正常工作。我找到了这个人,但他并没有很好地解

    • 我正在尝试用liquibase为一些测试设置数据库模式和一些测试数据。每个测试都有一个单独的changelog,它为测试设置模式和一些特定的数据。 为了使我的测试工作,我需要在每次测试之前删除模式,并用新的测试数据填充它。然而,这似乎并不奏效,因为有些测试正在失败,因为旧的测试数据仍然可用。我觉得我的配置有些东西不对。如何在每次测试之前强制liquibase删除模式?