冰河技术
导读
♻学习路线
  • 面试必问系列

    • 面试必问
  • 架构与模式

    • Java极简设计模式
    • 实战高并发设计模式
  • Java核心技术

    • Java8新特性
    • IOC核心技术
    • JVM调优技术
  • 容器化核心技术

    • Dockek核心技术
  • 分布式存储

    • Mycat核心技术
  • 数据库核心技术

    • MySQL基础篇
  • 服务器核心技术

    • Nginx核心技术
  • 渗透核心技术

    • 渗透实战技术
  • 底层技术
  • 源码分析
  • 基础案例
  • 实战案例
  • 面试
  • 系统架构
  • Spring6核心技术
  • 分布式事务

    • 分布式事务系列视频
  • SpringBoot
  • SpringCloudAlibaba
  • 🔥AI大模型项目

    • 一站式AI智能平台
    • AI智能客服系统
    • AI智能问答系统
    • 实战AI大模型
  • 中间件项目

    • 手写高性能Redis组件
    • 手写高性能脱敏组件
    • 手写线程池项目
    • 手写高性能SQL引擎
    • 手写高性能Polaris网关
    • 手写高性能RPC项目
  • 高并发项目

    • 分布式IM即时通讯系统(新)
    • 分布式Seckill秒杀系统
    • 实战高并发设计模式
  • 微服务项目

    • 简易电商脚手架项目
  • 手撕源码

    • 手撕Spring6源码
🌍知识星球
  • 总览

    • 《书籍汇总》
  • 出版图书

    • 《深入理解高并发编程:核心原理与案例实战》
    • 《深入理解高并发编程:JDK核心技术》
    • 《深入高平行開發:深度原理&專案實戰》
    • 《深入理解分布式事务:原理与实战》
    • 《MySQL技术大全:开发、优化与运维实战》
    • 《海量数据处理与大数据技术实战》
  • 电子书籍

    • 《实战高并发设计模式》
    • 《深入理解高并发编程(第2版)》
    • 《深入理解高并发编程(第1版)》
    • 《从零开始手写RPC框架(基础篇)》
    • 《SpringCloud Alibaba实战》
    • 《冰河的渗透实战笔记》
    • 《MySQL核心知识手册》
    • 《Spring IOC核心技术》
  • 关于自己
  • 关于学习
  • 关于职场
B站
Github
导读
♻学习路线
  • 面试必问系列

    • 面试必问
  • 架构与模式

    • Java极简设计模式
    • 实战高并发设计模式
  • Java核心技术

    • Java8新特性
    • IOC核心技术
    • JVM调优技术
  • 容器化核心技术

    • Dockek核心技术
  • 分布式存储

    • Mycat核心技术
  • 数据库核心技术

    • MySQL基础篇
  • 服务器核心技术

    • Nginx核心技术
  • 渗透核心技术

    • 渗透实战技术
  • 底层技术
  • 源码分析
  • 基础案例
  • 实战案例
  • 面试
  • 系统架构
  • Spring6核心技术
  • 分布式事务

    • 分布式事务系列视频
  • SpringBoot
  • SpringCloudAlibaba
  • 🔥AI大模型项目

    • 一站式AI智能平台
    • AI智能客服系统
    • AI智能问答系统
    • 实战AI大模型
  • 中间件项目

    • 手写高性能Redis组件
    • 手写高性能脱敏组件
    • 手写线程池项目
    • 手写高性能SQL引擎
    • 手写高性能Polaris网关
    • 手写高性能RPC项目
  • 高并发项目

    • 分布式IM即时通讯系统(新)
    • 分布式Seckill秒杀系统
    • 实战高并发设计模式
  • 微服务项目

    • 简易电商脚手架项目
  • 手撕源码

    • 手撕Spring6源码
🌍知识星球
  • 总览

    • 《书籍汇总》
  • 出版图书

    • 《深入理解高并发编程:核心原理与案例实战》
    • 《深入理解高并发编程:JDK核心技术》
    • 《深入高平行開發:深度原理&專案實戰》
    • 《深入理解分布式事务:原理与实战》
    • 《MySQL技术大全:开发、优化与运维实战》
    • 《海量数据处理与大数据技术实战》
  • 电子书籍

    • 《实战高并发设计模式》
    • 《深入理解高并发编程(第2版)》
    • 《深入理解高并发编程(第1版)》
    • 《从零开始手写RPC框架(基础篇)》
    • 《SpringCloud Alibaba实战》
    • 《冰河的渗透实战笔记》
    • 《MySQL核心知识手册》
    • 《Spring IOC核心技术》
  • 关于自己
  • 关于学习
  • 关于职场
B站
Github
  • 开篇:专栏介绍

    • 开篇:我要带你从零开始手搓一个大厂必备的高性能Redis组件
  • 第01部分:需求设计

    • 第01节:为何要学习高性能Redis组件
    • 第02节:高性能Redis组件的目标与挑战
    • 第03节:高性能Redis组件需求与功能梳理
  • 第02部分:总体架构设计

    • 第01节:高性能Redis组件总体方案目标
  • 第03部分:落地实现

    • 第01节:高性能Redis组件基础功能设计与实现
    • 第02节:高性能Redis组件分布式锁设计与实现
    • 第03节:高性能Redis组件防缓存击穿、穿透和雪崩的核心设计与实现
  • 第04部分:测试验证

    • 第01节:高性能Redis组件单元测试场景验证
    • 第02节:高性能Redis组件基准性能测试
  • 专栏总结

    • 总结:高性能Redis组件整体专栏总结

《高性能Redis组件》测试验证-第01节:高性能Redis组件单元测试场景验证

作者:冰河
星球:http://m6z.cn/6aeFbs
博客:https://binghe.site
文章汇总:https://binghe.site/md/all/all.html
源码获取地址:https://t.zsxq.com/0dhvFs5oR

沉淀,成长,突破,帮助他人,成就自我。

  • 本章难度:★★☆☆☆
  • 本章重点:对高性能Redis组件实现的脱敏功能进行单元测试,从总体上理解高性能Redis组件防缓存击穿、穿透和雪崩问题的核心设计思想,并从全局视角了解高性能Redis组件的设计和架构思想,并能够将其灵活应用到自身实际项目中。

大家好,我是冰河~~

有一定工作经验的小伙伴都知道,在实际工作中,我们自己开发的功能在提测前,都是需要我们自己编写单元测试,并且需要所有单元测试都通过后才能提交测试的。高性能Redis组件亦是如此,我们开发完高性能Redis组件的核心功能后,也需要对功能进行单元测试。

一、前言

截止到目前,我们完成了高性能Redis组件的核心功能,包括:基础功能的设计与实现、分布锁的设计与实现、防缓存击穿、穿透和雪崩的核心设计与实现。这些落地实现的代码功能是否符合我们的预期,就需要针对落地实现的方法进行单元测试。所以,接下来,我们要对高性能Redis组件对外提供的接口方法进行单元测试。

二、本节诉求

对高性能Redis组件实现的脱敏功能进行单元测试,从总体上理解高性能Redis组件防缓存击穿、穿透和雪崩问题的核心设计思想,并从全局视角了解高性能Redis组件的设计和架构思想,并能够将其灵活应用到自身实际项目中。

三、单元测试验证

本节,会对高性能Redis组件接口对外提供的方法进行单元测试。

3.1 创建测试模型

为了更好的进行单元测试,在正式进行单元测试之前,创建单元测试的对象模型User类。User类的代码也比较简单,就是一个包含id和name的实体类。

源码详见:io.binghe.redis.plugin.test.bean.User。

public class User {

    private Long id;
    private String name;

    public User() {
    }

    public User(Long id, String name) {
        this.id = id;
        this.name = name;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return JSONUtil.toJsonStr(this);
    }
}

3.2 编写单元测试

创建DistributeCacheServiceTest类编写单元测试方法。

DistributeCacheServiceTest类的源码详见:io.binghe.redis.plugin.test.DistributeCacheServiceTest。

@SpringBootTest
@RunWith(SpringRunner.class)
public class DistributeCacheServiceTest {

    @Autowired
    private DistributeCacheService distributeCacheService;


    @Test
    public void testQueryWithPassThrough(){
        User user = distributeCacheService.queryWithPassThrough("pass:through:", 1002852L, User.class,  this::getUser, 60L, TimeUnit.SECONDS);
        System.out.println(JSONUtil.toJsonStr(user));
    }
    @Test
    public void testQueryWithPassThroughWithoutArgs(){
        User user = distributeCacheService.queryWithPassThroughWithoutArgs("pass:through001:", User.class,  this::getUserWithoutArgs, 60L, TimeUnit.SECONDS);
        System.out.println(JSONUtil.toJsonStr(user));
    }

    @Test
    public void testQuerySimpleDataWithPassThrough(){
        Integer id = distributeCacheService.queryWithPassThrough("pass:through2:", 100285210, Integer.class,  this::getId, 60L, TimeUnit.SECONDS);
        System.out.println(id);
    }
    @Test
    public void testQuerySimpleDataWithPassThroughWithoutArgs(){
        Integer id = distributeCacheService.queryWithPassThroughWithoutArgs("pass:through2002:",  Integer.class,  this::getIdWithoutArgs, 60L, TimeUnit.SECONDS);
        System.out.println(id);
    }

    @Test
    public void testQueryWithPassThroughList(){
        List<User> list = distributeCacheService.queryWithPassThroughList("pass:through:list:", null, User.class, this::getUserList, 60L, TimeUnit.SECONDS);
        System.out.println(JSONUtil.toJsonStr(list));
    }
    @Test
    public void testQueryWithPassThroughListWithoutArgs(){
        List<User> list = distributeCacheService.queryWithPassThroughListWithoutArgs("pass:through:list003:", User.class, this::getUserListWithoutArgs, 60L, TimeUnit.SECONDS);
        System.out.println(JSONUtil.toJsonStr(list));
    }

    @Test
    public void testQuerySimpleDataWithPassThroughList(){
        List<Integer> list = distributeCacheService.queryWithPassThroughList("pass:through:list2:", 100285211, Integer.class, this::getIds, 60L, TimeUnit.SECONDS);
        System.out.println(JSONUtil.toJsonStr(list));
    }
    @Test
    public void testQuerySimpleDataWithPassThroughListWithoutArgs(){
        List<Integer> list = distributeCacheService.queryWithPassThroughListWithoutArgs("pass:through:list2004:", Integer.class, this::getIdsWithoutArgs, 60L, TimeUnit.SECONDS);
        System.out.println(JSONUtil.toJsonStr(list));
    }

    @Test
    public void testQueryWithLogicalExpire(){
        User user = distributeCacheService.queryWithLogicalExpire("logical:expire:", 1002852L, User.class,  this::getUser, 60L, TimeUnit.SECONDS);
        System.out.println(JSONUtil.toJsonStr(user));
    }

    @Test
    public void testQueryWithLogicalExpireWithoutArgs(){
        User user = distributeCacheService.queryWithLogicalExpireWithoutArgs("logical:expire005:", User.class,  this::getUserWithoutArgs, 60L, TimeUnit.SECONDS);
        System.out.println(JSONUtil.toJsonStr(user));
    }

    @Test
    public void testQuerySimpleDataWithLogicalExpire(){
        Integer id = distributeCacheService.queryWithLogicalExpire("logical:expire2:", 100285212, Integer.class,  this::getId, 60L, TimeUnit.SECONDS);
        System.out.println(id);
    }
    @Test
    public void testQuerySimpleDataWithLogicalExpireWithoutArgs(){
        Integer id = distributeCacheService.queryWithLogicalExpireWithoutArgs("logical:expire2006:", Integer.class,  this::getIdWithoutArgs, 60L, TimeUnit.SECONDS);
        System.out.println(id);
    }

    @Test
    public void testQueryWithLogicalExpireList(){
        List<User> list = distributeCacheService.queryWithLogicalExpireList("logical:expire:list:", null, User.class, this::getUserList, 60L, TimeUnit.SECONDS);
        System.out.println(JSONUtil.toJsonStr(list));
    }
    @Test
    public void testQueryWithLogicalExpireListWithoutArgs(){
        List<User> list = distributeCacheService.queryWithLogicalExpireListWithoutArgs("logical:expire:list007:", User.class, this::getUserListWithoutArgs, 60L, TimeUnit.SECONDS);
        System.out.println(JSONUtil.toJsonStr(list));
    }

    @Test
    public void testQuerySimpleDataWithLogicalExpireList(){
        List<Integer> list = distributeCacheService.queryWithLogicalExpireList("logical:expire:list2:", 100285213, Integer.class, this::getIds, 60L, TimeUnit.SECONDS);
        System.out.println(JSONUtil.toJsonStr(list));
    }
    @Test
    public void testQuerySimpleDataWithLogicalExpireListWithoutArgs(){
        List<Integer> list = distributeCacheService.queryWithLogicalExpireListWithoutArgs("logical:expire:list2008:", Integer.class, this::getIdsWithoutArgs, 60L, TimeUnit.SECONDS);
        System.out.println(JSONUtil.toJsonStr(list));
    }

    @Test
    public void testQueryWithMutex(){
        User user = distributeCacheService.queryWithMutex("mutex:", 1002852L, User.class,  this::getUser, 60L, TimeUnit.SECONDS);
        System.out.println(JSONUtil.toJsonStr(user));
    }
    @Test
    public void testQueryWithMutexWithoutArgs(){
        User user = distributeCacheService.queryWithMutexWithoutArgs("mutex009:", User.class,  this::getUserWithoutArgs, 60L, TimeUnit.SECONDS);
        System.out.println(JSONUtil.toJsonStr(user));
    }

    @Test
    public void testQuerySimpleDataWithMutex(){
        Integer id = distributeCacheService.queryWithMutex("mutex2:", 100285214, Integer.class,  this::getId, 60L, TimeUnit.SECONDS);
        System.out.println(id);
    }
    @Test
    public void testQuerySimpleDataWithMutexWithoutArgs(){
        Integer id = distributeCacheService.queryWithMutexWithoutArgs("mutex2010:", Integer.class,  this::getIdWithoutArgs, 60L, TimeUnit.SECONDS);
        System.out.println(id);
    }

    @Test
    public void testQueryWithMutexList(){
        List<User> list = distributeCacheService.queryWithMutexList("mutex:list:", null, User.class, this::getUserList, 60L, TimeUnit.SECONDS);
        System.out.println(JSONUtil.toJsonStr(list));
    }
    @Test
    public void testQueryWithMutexListWithoutArgs(){
        List<User> list = distributeCacheService.queryWithMutexListWithoutArgs("mutex:list011:", User.class, this::getUserListWithoutArgs, 60L, TimeUnit.SECONDS);
        System.out.println(JSONUtil.toJsonStr(list));
    }

    @Test
    public void testQuerySimpleDataWithMutexList(){
        List<Integer> list = distributeCacheService.queryWithMutexList("mutex:list2:", 123, Integer.class, this::getIds, 60L, TimeUnit.SECONDS);
        System.out.println(JSONUtil.toJsonStr(list));
    }

    @Test
    public void testQuerySimpleDataWithMutexListWithoutArgs(){
        List<Integer> list = distributeCacheService.queryWithMutexListWithoutArgs("mutex:list2012:", Integer.class, this::getIdsWithoutArgs, 60L, TimeUnit.SECONDS);
        System.out.println(JSONUtil.toJsonStr(list));
    }

    /**
     * 模拟带参数从数据库查询对象
     */
    public User getUser(Long id){
        return new User(id, "binghe");
    }

    /**
     * 默认不带参数从数据库查询对象
     */
    public User getUserWithoutArgs(){
        return new User(1L, "binghe");
    }

    /**
     * 模拟带参数查询从数据库对象列表
     */
    public List<User> getUserList(String type){
        return Arrays.asList(
                new User(1L, "binghe001"),
                new User(2L, "binghe002"),
                new User(3L, "binghe003")
        );
    }

    /**
     * 模拟不带参数从数据库查询对象列表
     */
    public List<User> getUserListWithoutArgs(){
        return Arrays.asList(
                new User(1L, "binghe001"),
                new User(2L, "binghe002"),
                new User(3L, "binghe003")
        );
    }

    /**
     * 模拟带参数从数据库查询简单数据类型数据
     */
    public Integer getId(Integer id){
        return id;
    }

    /**
     * 模拟不带参数从数据库查询简单数据类型数据
     */
    public Integer getIdWithoutArgs(){
        return 0;
    }

    /**
     * 模拟带参数从数据库查询简单数据类型数据列表
     */
    public List<Integer> getIds(Integer id){
        return Arrays.asList(0,0,0);
    }

    /**
     * 模拟不带参数从数据库查询简单数据类型数据列表
     */
    public List<Integer> getIdsWithoutArgs(){
        return Arrays.asList(0,0,0);
    }
}

四、测试验证

测试验证的主要步骤如下所示。

(1)启动Redis

启动Redis,这里我直接在本地启动一个Redis服务,IP地址为127.0.0.1,端口为6379。

(2)配置application.yml

在项目的src/main/resources目录下创建application.yml文件,配置如下内容。

spring:
  application:
    name: redis-plugin

  redis:
    database: 0
    host: 127.0.0.1
    port: 6379
    password:
    timeout: 30000
    lettuce:
      pool:
        enabled: true
        max-active: 8
        max-idle: 8
        min-idle: 0
        max-wait: 5000
    address: redis://127.0.0.1:6379

cache:
  type:
    distribute: redis

distribute:
  type:
    lock: redisson

redis:
  arrange:
    type: single # single or cluster

(3)运行单元测试

运行DistributeCacheServiceTest类的所有代码,运行结果如下所示。


从测试结果来看,高性能Redis组件对外提供的接口方法所有单元测试用例全部验证通过,并且打印的结果数据也符合我们的预期。

注意:这里,我们是实际访问Redis进行的单元测试,在实际工作中,编写单元测试一般是通过Mock方式进行的,单元测试代码不允许依赖外部环境资源,例如,不允许依赖数据库、Redis等。关于如何使用Mock编写单元测试,后续我会单独开一个专栏专门讲解,这里就不再赘述。

五、本节总结

本节,主要对高性能Redis组件提供的核心功能进行了单元测试,主要是对高性能Redis组件对外提供的接口方法进行了全面的单元测试,测试结果符合我们的预期。

最后,可以在评论区写下你学完本章节的收获,祝大家都能学有所成,我们一起搞定高性能Redis组件。

六、写在最后

在冰河的知识星球除了热更的AI大模型外,还有其他十几个项目,像实战AI大模型、手写高性能敏组件、手写线程池、手写高性能SQL引擎、手写高性能Polaris网关、手写高性能熔断组件、手写通用指标上报组件、手写高性能数据库路由组件、手写分布式IM即时通讯系统、手写Seckill分布式秒杀系统、手写高性能RPC、实战高并发设计模式、简易商城系统等等。

这些项目的需求、方案、架构、落地等均来自互联网真实业务场景,让你真正学到互联网大厂的业务与技术落地方案,并将其有效转化为自己的知识储备。

值得一提的是:冰河自研的Polaris高性能网关比某些开源网关项目性能更高,目前正在热更AI大模型项目,也正在实现MCP,实战AI大模型正在热更中,全程带你分析原理和手撸代码。

你还在等啥?不少小伙伴经过星球硬核技术和项目的历练,早已成功跳槽加薪,实现薪资翻倍,而你,还在原地踏步,抱怨大环境不好。抛弃焦虑和抱怨,我们一起塌下心来沉淀硬核技术和项目,让自己的薪资更上一层楼。


目前,领券加入星球就可以跟冰河一起学习《DeepSeek大模型》、《手写高性能脱敏组件》、《手写线程池》、《手写高性能SQL引擎》、《手写高性能Polaris网关》、《手写高性能RPC项目》、《分布式Seckill秒杀系统》、《分布式IM即时通讯系统》《手写高性能通用熔断组件项目》、《手写高性能通用监控指标上报组件》、《手写高性能数据库路由组件》、《手写简易商城脚手架项目》、《Spring6核心技术与源码解析》和《实战高并发设计模式》,从零开始介绍原理、设计架构、手撸代码。

花很少的钱就能学这么多硬核技术、中间件项目和大厂秒杀系统与分布式IM即时通讯系统,比其他培训机构不知便宜多少倍,硬核多少倍,如果是我,我会买他个十年!

加入要趁早,后续还会随着项目和加入的人数涨价,而且只会涨,不会降,先加入的小伙伴就是赚到。

另外,还有一个限时福利,邀请一个小伙伴加入,冰河就会给一笔 分享有奖 ,有些小伙伴都邀请了50+人,早就回本了!

七、其他方式加入星球

  • 链接 :打开链接 http://m6z.cn/6aeFbs 加入星球。
  • 回复 :在公众号 冰河技术 回复 星球 领取优惠券加入星球。

特别提醒: 苹果用户进圈或续费,请加微信 hacker_binghe 扫二维码,或者去公众号 冰河技术 回复 星球 扫二维码加入星球。

好了,今天就到这儿吧,我是冰河,我们下期见~~

在 GitHub 上编辑此页
上次更新: 2026/4/29 16:18
Contributors: binghe001
Next
第02节:高性能Redis组件基准性能测试
阅读全文
×

扫码或搜索:冰河技术
发送:290992
即可立即永久解锁本站全部文章

星球会员
跳转链接