MockMvc 足以在集成测试中测试服务器响应吗?

问题描述 投票:0回答:1

我有一个端点

/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 的论据是什么?

java spring spring-boot integration-testing mockmvc
1个回答
0
投票

从我的角度来看,最好不要使用

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 文档:MockMvc 与端到端测试

Spring 文档:测试 Spring Boot 应用程序

一些集成测试示例

© www.soinside.com 2019 - 2024. All rights reserved.