使用MockMvc与SpringBootTest和使用WebMvcTest之间的区别
我是Spring Boot的新手,并试图了解如何在SpringBoot中测试。我有点困惑的是以下两个代码段之间的区别:使用MockMvc与SpringBootTest和使用WebMvcTest之间的区别
代码片段:
@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!")));
}
}
本次测试使用,我相信是有片测试和@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!")));
}
}
本试验采用@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!"));
}
}
非常好的问题。
@SpringBootTest
是一般测试注释。如果你正在寻找在1.4之前做同样事情的东西,那就是你应该使用的东西。它不会使用切片,这意味着它将启动完整的应用程序上下文,并且根本不会自定义组件扫描。
@WebMvcTest
只会扫描您定义的控制器和MVC基础结构。而已。因此,如果您的控制器对服务层中的其他bean具有一些依赖性,那么只有在您自己加载配置或为其提供模拟之前,测试才会启动。由于我们只加载应用程序的一小部分,因此速度更快。此注释使用切片。
Reading the doc应该也可以帮助你。
@SpringBootTest注释告诉Spring Boot去找一个主要的配置类(例如一个带有@SpringBootApplication的实例),并用它来启动一个Spring应用程序上下文。 SpringBootTest加载完整的应用程序并注入可能很慢的所有bean。
@WebMvcTest - 用于测试控制器层,您需要提供使用模拟对象所需的其余依赖关系。
以下几个注释供您参考。
测试应用程序 切片有时你想测试应用程序的一个简单的“切片”,而不是自动配置整个应用程序的。春季启动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
非常感谢响应!。因此,如果我理解正确,那么这意味着这两个代码片段仅测试应用程序的MVC部分。但是tcode代码片段1会加载完整的应用程序上下文,而代码片段2仅会扫描控制器。它是否正确?代码段1是否可以被视为测试控制器的单元测试? – Reshma
不,这是不正确的。 'SpringBootTest'正在加载您的完整应用程序(在某种程度上,默认情况下,如果有可用的,它将不会启动嵌入式容器,这就是'webEnvironment'的用途)。我不会说'@ SpringBootTest'是控制器的单元测试,但更多的是集成测试。 'WebMvcTest'实际上是对你的控制器的单元测试,因为如果它有依赖性,你必须自己提供它们(配置或某种模拟)。 –
再次感谢您的回复。我编辑了这个问题并添加了代码片段3.您提到@SpringBootTest注释更多地用于集成测试。我相信Snippet 3展示了这一点。因此,如果像Snippet 3那样完成集成测试,那么Snippet 2会做什么? Snippet 2使用SpringBootTest注释和一个模拟环境(wenEnvironment属性的默认值)。此外,代码片段3启动嵌入式服务器并进行真正的HTTP调用,而代码段2不执行此操作。所以考虑到这一点,不能将snippet 2视为单元测试? – Reshma