12.3.3 使用线上服务器进行测试

到目前为止,编写的测试依赖于 Spring WebFlux 框架的模拟实现,因此不需要真正的服务器。但可能需要在 Netty 或 Tomcat 等服务器的上下文中测试 WebFlux Controller,并且可能需要使用 repository 或其他依赖项。也就是说,可能需要编写一个集成测试。

要编写 WebTestClient 集成测试,首先使用 @RunWith@SpringBootTest 对测试类进行注解,就像其他任何 Spring Boot 集成测试一样:

package tacos;

import java.io.IOException;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.reactive.server.WebTestClient;

@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
public class TacoControllerWebTest {

  @Autowired
  private WebTestClient testClient;

}

通过将 webEnvironment 属性设置为 webEnvironment.RANDOM_PORT,将要求 Spring 启动正在运行的服务器来监听随机选择的端口。

WebTestClient 还将自动连接到测试类中。这不仅意味着将不再需要在测试方法中创建一个 URL,而且在发出请求时也不需要指定完整的 URL。这是因为 WebTestClient 将被装配成知道测试服务器在哪个端口上运行。现在可以将 shouldReturnRecentTacos() 重写为使用自动连线 WebTestClient 的集成测试:

@Test
public void shouldReturnRecentTacos() throws IOException {
  testClient.get().uri("/api/tacos?recent")
    .accept(MediaType.APPLICATION_JSON).exchange()
    .expectStatus().isOk()
    .expectBody()
      .jsonPath("$").isArray()
      .jsonPath("$.length()").isEqualTo(3)
      .jsonPath("$[?(@.name == 'Carnivore')]").exists()
      .jsonPath("$[?(@.name == 'Bovine Bounty')]").exists()
      .jsonPath("$[?(@.name == 'Veg-Out')]").exists();
}

毫无疑问,您已经注意到这个新版本的 shouldReturnRecentTacos() 的代码要少得多。因为将使用自动注入的实例,因此不再需要创建 WebTestClient。而且没有必要模拟 TacoRepository,因为 Spring 将创建 DesignTacoController 的一个实例,并为它注入一个真正的 TacoRepository。在这个新版本的测试方法中,使用 JSONPath 表达式来验证从数据库提供的值。

在测试过程中,当需要使用 WebFlux Controller 公开的 API 时,WebTestClient 非常有用。但是,当应用程序本身使用其他 API 时呢?让我们把注意力转向 Spring 的响应式 web 的客户端,看看 WebClient 是如何提供 REST 客户端来处理诸如 Mono 和 Flux 之类的响应式类型的。

results matching ""

    No results matching ""