我有一个端点
/api/employees
,想要测试 http 请求是否得到正确处理。我是 Spring Boot 的新手,并且参加了集成测试课程。完成本课程后,我预计以下测试将对我的应用程序进行 http 调用,并且我可以测试应用程序是否按预期运行(请参阅 此存储库 了解完整的示例存储库)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
public class EmployeeControllerH2IT {
@Autowired
private MockMvc mockMvc;
@Autowired
private EmployeeRepository employeeRepository;
@Autowired
private ObjectMapper objectMapper;
private Employee employee;
@BeforeEach
void setup() {
employeeRepository.deleteAll();
employee =
Employee.builder().firstName("John").lastName("Doe").email("[email protected]").build();
}
@Test
void givenEmployeeObject_whenCreateEmployee_thenReturnSavedEmployee() throws Exception {
ResultActions response =
mockMvc.perform(post("/api/employees").contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(employee)));
response.andDo(print()).andExpect(status().isCreated())
.andExpect(jsonPath("$.firstName", is(employee.getFirstName())))
.andExpect(jsonPath("$.lastName", is(employee.getLastName())))
.andExpect(jsonPath("$.email", is(employee.getEmail())));
assertThat(employeeRepository.count()).isEqualTo(1);
}
}
今天我了解到MockMvc并没有真正通过网络发送请求(我可以通过名字猜到它,我以为它是一个普通的http客户端,但针对@WebMvcTests进行了优化)。
我现在的问题是:MockMvc 是否足以在集成测试中测试正确的服务器响应?或者应该在网络上运行“真正的”集成测试(使用“真正的”http 客户端作为
RestTemplate
或 OkHttp
)?我想答案是“这取决于”,但是这里支持/反对mockmvc的论据是什么?
从我的角度来看,最好不要使用
MockMvc
进行集成测试,因为这些测试应该接近生产环境。换句话说,最好使用真实的组件,包括真实的 Web 环境,而不是尽可能使用模拟。
在您的情况下,您使用
MockMvc
创建一个 MockHttpServletRequest
,但同时您使用 SpringBootTest.WebEnvironment.RANDOM_PORT
启动真正的网络环境:
RANDOM_PORT:加载WebServerApplicationContext并提供真实的 网络环境。嵌入式服务器启动并随机监听 港口。
我更喜欢使用
SpringBootTest.WebEnvironment.RANDOM_PORT
与 WebTestClient
的组合进行集成测试,使用 SpringBootTest.WebEnvironment.MOCK
(默认为 @SpringBootTest
)与 MockMvc
进行组件测试,或者简单地使用 MockMvc
进行 @WebMvcTest
。
此外,您无法使用文档中的
MockMvc
来测试所有内容:
由于嘲笑发生在 Spring MVC层,依赖于下层servlet容器的代码 无法直接使用 MockMvc 测试行为。
例如,您可以将 servlet 路径添加到您的
application.yaml
,如下所示:
spring:
mvc:
servlet:
path: /custom
想象我们还有一个控制器方法:
@GetMapping(path = "/orders")
@ResponseStatus(HttpStatus.OK)
public void foo() {
}
在真实的网络环境下,使用
WebTestClient
,您必须向/custom/orders
发送请求。向 /orders
发送请求将导致 404 错误,就像在生产代码中一样。
但是,如果您使用
MockMvc
,对 /orders
的相同请求将返回 200 状态代码,即使在生产中会失败并返回 404。
Spring 文档的一些链接: