23-01-31
banq
Hoverfly是一个轻量级服务虚拟化工具,允许您存根或模拟 HTTP(S) 服务。 Hoverfly Java 是一种本地语言绑定,它为您提供了一个用于在 Java 中管理 Hoverfly 的富有表现力的 API。它为您提供了一个抽象了二进制和 API 调用的 Hoverfly 类、一个用于创建模拟的 DSL 以及一个用于在单元测试中使用它的 JUnit 集成。
可以在不同的模式下执行测试,如模拟、间谍、捕获或差异。您可以使用 Java DSL 构建请求匹配器到响应映射。
让我们在 Maven 依赖项中包含最新版本的 Hoverfly:
<dependency> <groupId>io.specto</groupId> <artifactId>hoverfly-java-junit5</artifactId> <version>0.14.3</version> </dependency> |
假设我们的 Spring 中有以下方法@RestController。在为自己返回 ping 响应之前,它会调用 address 下的另一个服务http://callme-service:8080/callme/ping。
@GetMapping("/ping") public String ping() { String response = restTemplate .getForObject("http://callme-service:8080/callme/ping", String.class); LOGGER.info("Calling: response={}", response); return "I'm caller-service " + version + ". Calling... " + response; } |
现在,我们将为我们的控制器创建测试。为了使用 Hoverfly 拦截传出流量:
- 我们注册了 HoverflyExtension。
- 然后我们可以使用 Hoverfly 对象来创建请求和模拟 HTTP 响应。
模拟的响应体是I'm callme-service v1。
@SpringBootTest(properties = {"VERSION = v2"}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @ExtendWith(HoverflyExtension.class) // (1) public class CallerCallmeTest { @Autowired TestRestTemplate restTemplate; @Test void callmeIntegration(Hoverfly hoverfly) { hoverfly.simulate( dsl(service("http://callme-service:8080") .get("/callme/ping") .willReturn(success().body("I'm callme-service v1."))) ); // (2) String response = restTemplate .getForObject("/caller/ping", String.class); assertEquals("I'm caller-service v2. Calling... I'm callme-service v1.", response); } } |
我们可以通过@HoverflyConfig注解轻松定制Hovefly行为。默认情况下,Hoverfly在代理模式下工作。
假设我们希望它作为一个网络Web服务器,我们需要将属性webserver设置为true (1)。
之后,它将在localhost和proxyPort属性所指示的端口上监听请求。在下一步,我们还将启用Spring Cloud @LoadBalancedClient来配置目标URL的静态列表,而不是动态发现(2)。
最后,我们可以创建一个Hoverfly测试:这一次,我们将拦截来自监听在localhost:8080上的Web服务器的流量(3)。
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @HoverflyCore(config = @HoverflyConfig(logLevel = LogLevel.DEBUG, webServer = true, proxyPort = 8080)) // (1) @ExtendWith(HoverflyExtension.class) @LoadBalancerClient(name = "account-service", configuration = AccountServiceConf.class) // (2) public class GatewayTests { @Autowired TestRestTemplate restTemplate; @Test public void findAccounts(Hoverfly hoverfly) { hoverfly.simulate(dsl( service("http://localhost:8080") .andDelay(200, TimeUnit.MILLISECONDS).forAll() .get(any()) .willReturn(success("[{\"id\":\ŕ\",\"number\":\\",\"balance\":5000}]", "application/json")))); // (3) ResponseEntity<String> response = restTemplate .getForEntity("/account/1", String.class); Assertions.assertEquals(200, response.getStatusCodeValue()); Assertions.assertNotNull(response.getBody()); } } |
下面是为测试目的而创建的负载均衡器客户端配置。
class AccountServiceInstanceListSuppler implements ServiceInstanceListSupplier { private final String serviceId; AccountServiceInstanceListSuppler(String serviceId) { this.serviceId = serviceId; } @Override public String getServiceId() { return serviceId; } @Override public Flux<List<ServiceInstance>> get() { return Flux.just(Arrays .asList(new DefaultServiceInstance(serviceId + "1", serviceId, "localhost", 8080, false))); } } |