本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford

通过单元测试,我们也可以了解下一般我们实现 spring cloud 自定义的基础组件,怎么去单元测试。

这里的单元测试主要测试三个场景:

  1. 只返回同一个 zone 下的实例,其他 zone 的不会返回
  2. 对于多个请求,每个请求返回的与上次的实例不同。
  3. 对于多线程的每个请求,如果重试,返回的都是不同的实例

同时,我们也需要针对同步和异步两个配置,分别进行测试,同步和异步两种配置测试逻辑是一样的,只是测试的 Bean 不一样

  • 同步环境是 DiscoveryClient,异步环境是 ReactiveDiscoveryClient
  • 同步环境负载均衡器是 LoadBalancer,异步环境负载均衡器是 ReactiveLoadBalancer

同步测试代码请参考LoadBalancerTest.java异步测试代码请参考LoadBalancerTest.java

我们这里使用同步测试代码作为例子展示:

//SpringExtension也包含了MockitoJUnitRunner,所以 @Mock 等注解也生效了
@ExtendWith(SpringExtension.class)
@SpringBootTest(properties = {LoadBalancerEurekaAutoConfiguration.LOADBALANCER_ZONE + "=zone1"})
public class LoadBalancerTest { @EnableAutoConfiguration
@Configuration
public static class App {
@Bean
public DiscoveryClient myDiscoveryClient() {
ServiceInstance zone1Instance1 = Mockito.spy(ServiceInstance.class);
ServiceInstance zone1Instance2 = Mockito.spy(ServiceInstance.class);
ServiceInstance zone2Instance3 = Mockito.spy(ServiceInstance.class);
Map<String, String> zone1 = Map.ofEntries(
Map.entry("zone", "zone1")
);
Map<String, String> zone2 = Map.ofEntries(
Map.entry("zone", "zone2")
);
when(zone1Instance1.getMetadata()).thenReturn(zone1);
when(zone1Instance1.getInstanceId()).thenReturn("instance1");
when(zone1Instance2.getMetadata()).thenReturn(zone1);
when(zone1Instance2.getInstanceId()).thenReturn("instance2");
when(zone2Instance3.getMetadata()).thenReturn(zone2);
when(zone2Instance3.getInstanceId()).thenReturn("instance3");
DiscoveryClient spy = Mockito.spy(DiscoveryClient.class);
Mockito.when(spy.getInstances("testService"))
.thenReturn(List.of(zone1Instance1, zone1Instance2, zone2Instance3));
return spy;
}
} @SpyBean
private LoadBalancerClientFactory loadBalancerClientFactory;
@SpyBean
private Tracer tracer; /**
* 只返回同一个 zone 下的实例
*/
@Test
public void testFilteredByZone() {
ReactiveLoadBalancer<ServiceInstance> testService =
loadBalancerClientFactory.getInstance("testService");
for (int i = 0; i < 100; i++) {
ServiceInstance server = Mono.from(testService.choose()).block().getServer();
//必须处于和当前实例同一个zone下
Assertions.assertEquals(server.getMetadata().get("zone"), "zone1");
}
} /**
* 返回不同的实例
*/
@Test
public void testReturnNext() {
ReactiveLoadBalancer<ServiceInstance> testService =
loadBalancerClientFactory.getInstance("testService");
Span span = tracer.nextSpan();
for (int i = 0; i < 100; i++) {
try (Tracer.SpanInScope cleared = tracer.withSpanInScope(span)) {
ServiceInstance server1 = Mono.from(testService.choose()).block().getServer();
ServiceInstance server2 = Mono.from(testService.choose()).block().getServer();
//每次选择的是不同实例
Assertions.assertNotEquals(server1.getInstanceId(), server2.getInstanceId());
}
}
} /**
* 跨线程,默认情况下是可能返回同一实例的,在我们的实现下,保持
* span 则会返回下一个实例,这样保证多线程环境同一个 request 重试会返回下一实例
*
* @throws Exception
*/
@Test
public void testSameSpanReturnNext() throws Exception {
Span span = tracer.nextSpan();
for (int i = 0; i < 100; i++) {
try (Tracer.SpanInScope cleared = tracer.withSpanInScope(span)) {
ReactiveLoadBalancer<ServiceInstance> testService =
loadBalancerClientFactory.getInstance("testService");
ServiceInstance server1 = Mono.from(testService.choose()).block().getServer();
AtomicReference<ServiceInstance> server2 = new AtomicReference<>();
Thread thread = new Thread(() -> {
try (Tracer.SpanInScope cleared2 = tracer.withSpanInScope(span)) {
server2.set(Mono.from(testService.choose()).block().getServer());
}
});
thread.start();
thread.join();
System.out.println(i);
Assertions.assertNotEquals(server1.getInstanceId(), server2.get().getInstanceId());
}
}
}
}

运行测试,测试通过。

我们这一节使用单元测试验证我们要实现的这些功能是否有效。下一节,我们将开始分析同步环境下的 Http 客户端,Open-Feign Client。

微信搜索“我的编程喵”关注公众号,每日一刷,轻松提升技术,斩获各种offer

SpringCloud升级之路2020.0.x版-24.测试Spring Cloud LoadBalancer的更多相关文章

  1. SpringCloud升级之路2020.0.x版-6.微服务特性相关的依赖说明

    本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford spring-cl ...

  2. SpringCloud升级之路2020.0.x版-20. 启动一个 Eureka Server 集群

    本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford 我们的业务集群结构 ...

  3. SpringCloud升级之路2020.0.x版-21.Spring Cloud LoadBalancer简介

    本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford 我们使用 Spri ...

  4. SpringCloud升级之路2020.0.x版-23.订制Spring Cloud LoadBalancer

    本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford 我们使用 Spri ...

  5. SpringCloud升级之路2020.0.x版-33. 实现重试、断路器以及线程隔离源码

    本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 在前面两节,我们梳理了实现 Feign 断路器以及线程隔离的思路,并说明了如何优化目前的负 ...

  6. SpringCloud升级之路2020.0.x版-40. spock 单元测试封装的 WebClient(上)

    本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 我们来测试下前面封装好的 WebClient,这里开始,我们使用 spock 编写 gro ...

  7. SpringCloud升级之路2020.0.x版-40. spock 单元测试封装的 WebClient(下)

    本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 我们继续上一节,继续使用 spock 测试我们自己封装的 WebClient 测试针对 r ...

  8. SpringCloud升级之路2020.0.x版-1.背景

    本系列为之前系列的整理重启版,随着项目的发展以及项目中的使用,之前系列里面很多东西发生了变化,并且还有一些东西之前系列并没有提到,所以重启这个系列重新整理下,欢迎各位留言交流,谢谢!~ Spring ...

  9. SpringCloud升级之路2020.0.x版-41. SpringCloudGateway 基本流程讲解(1)

    本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 接下来,将进入我们升级之路的又一大模块,即网关模块.网关模块我们废弃了已经进入维护状态的 ...

随机推荐

  1. 数组去重汇总—v客学院技术分享

    上周基础班结束了数组的学习内容,这几天有时间整理了下几种比较常用的数组去重的方法供大家查阅!!!!! 话不多说,直接贴代码吧~~~~~~~ 欢迎大家指正,共同学习,一同进步!!! (php开发,web ...

  2. python -- 程序异常与调试(程序调试)

    一.程序调试 A.使用assert语句检测程序代码中的错误. assert 表达式[, 参数] 如果表达式为True,则继续往下运行:如果为False,则抛出一个AssertionError异常,并且 ...

  3. 一次搞懂JavaScript对象

    索引 目录 索引 1. 对象与类 2.对象使用 2.1 语法 2.2 属性 3.对象特性 4.对象的创建 4.1 字面量 4.2 工厂函数 4.3 构造函数 4.4 class类 4.5 对象与单例模 ...

  4. tomcat禁用PUT,DELETE等一些不必要的HTTP方法

    一.背景 公司进行安全整改, 技术要求:系统软件所需支撑的WEB容器环境应禁止除GET和POST外其他HTTP(S)方法. 提供凭证:建议在不影响业务的前提下,禁用PUT.DELETE.HEAD.OP ...

  5. 第1天 Mark Down 学习及DOS命令

    Markdown学习 标题 "#加空格"几个#就表示几级标题 字体 helloworld!一两个两个*号 helloworld!一边一个*号 helloworld! 一边三个号 h ...

  6. TCP协议系列之一一什么是TCP协议,TCP的三次握手,为什么不是2次或4次?

    CP 为什么三次握手而不是两次握手(正解版) https://blog.csdn.net/lengxiao1993/article/details/82771768 自己理解说明一下: 比如说有一条管 ...

  7. 从零开始了解kubernetes

    kubernetes 已经成为容器编排领域的王者,它是基于容器的集群编排引擎,具备扩展集群.滚动升级回滚.弹性伸缩.自动治愈.服务发现等多种特性能力. 本文将带着大家快速了解 kubernetes , ...

  8. 【动画消消乐 】HTML+CSS 吃豆豆动画 073

    前言 Hello!小伙伴! 非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出-   自我介绍 ଘ(੭ˊᵕˋ)੭ 昵称:海轰 标签:程序猿|C++选手|学生 简介:因C语言结识编程,随后转入计 ...

  9. python算法(2)兔子产子(斐波那切数列)

    兔子产子 1.问题描述 有一对兔子,从出生后的第3个月起每个月都生一对兔子.小兔子长到第3个月后每个月又生一对兔子,假设所有的兔子都不死,问30个月内每个月的兔子总对数为多少? 2.问题分析 兔子产子 ...

  10. 2021陕西省大学生网络安全技能大赛 Web ez_checkin

    web ez_checkin 进去看了一会,啥也没找到,直接上dirsearch 扫到一个index.php~,打开看一看,是php审计 <?php error_reporting(0); in ...