使用MockMvc与SpringBootTest和使用WebMvcTest之间的区别

Rev*_*sha 65 spring-boot

我是Spring Boot的新手,我正在尝试了解SpringBoot中的测试工作原理.我对以下两个代码片段之间的区别有点困惑:

代码段1:

@RunWith(SpringRunner.class)
@WebMvcTest(HelloController.class)
public class HelloControllerApplicationTest {
    @Autowired    
    private MockMvc mvc;

    @Test
    public void getHello() throws Exception {
        mvc.perform(MockMvcRequestBuilders.get("/").accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andExpect(content().string(equalTo("Greetings from Spring Boot!")));
    }
}
Run Code Online (Sandbox Code Playgroud)

此测试使用@WebMvcTest注释,我相信它是用于特征切片测试,并且仅测试Web应用程序的Mvc层.

代码段2:

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class HelloControllerTest {

    @Autowired
    private MockMvc mvc;

    @Test
    public void getHello() throws Exception {
    mvc.perform(MockMvcRequestBuilders.get("/").accept(MediaType.APPLICATION_JSON))
            .andExpect(status().isOk())
            .andExpect(content().string(equalTo("Greetings from Spring Boot!")));
    }
}
Run Code Online (Sandbox Code Playgroud)

此测试使用@SpringBootTest注释和MockMvc.那么这与代码片段1有何不同?这有什么不同的做法?

编辑:添加代码片段3(在Spring文档中将此作为集成测试的示例)

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class HelloControllerIT {

@LocalServerPort
private int port;

private URL base;

@Autowired
private TestRestTemplate template;

@Before
public void setUp() throws Exception {
    this.base = new URL("http://localhost:" + port + "/");
}

@Test
public void getHello() throws Exception {
    ResponseEntity<String> response = template.getForEntity(base.toString(),
            String.class);
    assertThat(response.getBody(), equalTo("Greetings from Spring Boot!"));
}
}
Run Code Online (Sandbox Code Playgroud)

Ste*_*oll 65

@SpringBootTest是一般测试注释.如果你正在寻找在1.4之前做同样事情的东西,那就是你应该使用的东西.它根本不使用切片,这意味着它将启动完整的应用程序上下文,而不是自定义组件扫描.

@WebMvcTest只会扫描您定义的控制器和MVC基础设施.而已.因此,如果您的控制器对服务层中的其他bean有一定的依赖性,那么在您自己加载该配置或为其提供模拟之前,测试将不会启动.这个速度要快得多,因为我们只加载你应用的一小部分.此注释使用切片.

阅读文档也应该对你有所帮助.

  • 我不确定我们会在这里解决这个问题。也许吉特?您似乎经常错过的事情是 `SpringBootTest` 和 `WebMvcTest` 创建的应用程序上下文大不相同。前者加载您的整个应用程序并启用所有自动配置,而后者仅启用 Spring Mvc 并且不扫描除“HelloController”之外的任何内容。毕竟,这完全取决于您所说的单元测试是什么意思。但这就是区别。 (6认同)
  • 不,这是不正确的。`SpringBootTest` 正在加载您的完整应用程序(在某种程度上,默认情况下,如果有可用的嵌入式容器,它不会启动嵌入式容器,这就是 `webEnvironment` 的用途)。我不会说“@SpringBootTest”是控制器的单元测试,但实际上更多的是集成测试。“WebMvcTest”实际上是控制器的单元测试,因为如果它具有依赖性,则您必须自己提供它们(配置或某种模拟)。 (2认同)

Ros*_*tha 45

@SpringBootTest注释告诉Spring Boot去寻找一个主配置类(例如一个带@SpringBootApplication),并使用它来启动Spring应用程序上下文.SpringBootTest加载完整的应用程序并注入所有可能很慢的bean.

@WebMvcTest - 用于测试控制器层,您需要使用模拟对象提供所需的剩余依赖项.

以下几点注释供您参考.

测试应用程序的切片 有时,您希望测试应用程序的简单"切片",而不是自动配置整个应用程序.Spring Boot 1.4引入了4个新的测试注释:

@WebMvcTest - for testing the controller layer
@JsonTest - for testing the JSON marshalling and unmarshalling
@DataJpaTest - for testing the repository layer
@RestClientTests - for testing REST clients
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请参阅:https://spring.io/guides/gs/testing-web/

  • 这里是[Spin​​g Boot参考 - 测试自动配置注释](https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-test-auto-configuration.html#test - 自动配置)。@roshankumar-mutha 在这里列出的不仅仅是四个。入门指南的链接并未深入介绍这些部分。 (3认同)

Gau*_*ula 7

MVC测试旨在仅覆盖应用程序的控制器部分。HTTP请求和响应是模拟的,因此不会创建实际的连接。另一方面,当您使用@SpringBootTest时,将加载Web应用程序上下文的所有配置,并且连接将通过真实的Web服务器。在这种情况下,您不使用MockMvc bean,而是使用标准的Res​​tTemplate(或新的替代TestRestTemplate)。

那么,我们什么时候应该选择一个?@WebMvcTest旨在从服务器端统一测试控制器。另一方面,当您要从客户端与应用程序进行交互时,应将@SpringBootTest用于集成测试。

这并不意味着您不能在@SpringBootTest中使用模拟程序。如果您正在编写集成测试,那仍然有必要。无论如何,最好不要仅将其用于简单控制器的单元测试。

源码-使用Spring Boot学习微服务

  • 我不明白为什么这个答案被赞成。当你使用`@SpringBootTest`时,真正的Web服务器不会启动,除非你还有`webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT`(或`DEFINED_PORT`)并且连接没有通过真正的网络服务器。“@SpringBootTest”的默认值是“WebEnvironment.MOCK”。 (8认同)