【消息队列开发】 测试MessageFileManager(对硬盘中的消息操作)类

文章目录

  • 🍃前言
  • 🎄测试流程
  • 🌴准备工作
  • 🌲测试创建队列功能
  • 🌳测试统计文件的读写
  • 🎋测试将相应消息放入文件中
  • 🎍测试读文件里的消息到内存
  • 🍀测试删除消息
  • 😎测试垃圾回收
  • ⭕总结

🍃前言

本次开发任务,对前面我们所完成的 MessageFileManager 类里的方法进行测试

在这里插入图片描述

🎄测试流程

与前面 DataBaseManager 测试流程相似,我们都需要准备

  1. 执行每个用例之前的准备工作
  2. 执行每个用例之后的收尾工作
  3. 准备一些基础数据

然后进行一功能的测试

🌴准备工作

首先我们实例化一个 MessageFileManager 的对象,方便后续进行调用

并提前给出两个队列的名字,这里只给了名字,并没有实例化,后续使用时,再具体实例化

在每个用例执行之前,我们都创建两个队列,队列名字为我们上面已经定义好了的

在每个用例执行之前,我们都需要销毁这两个队列

代码实现如下:

private MessageFileManager messageFileManager = new MessageFileManager();private static final String queueName1 = "testQueue1";
private static final String queueName2 = "testQueue2";// 这个方法是每个用例执行之前的准备工作
@BeforeEach
public void setUp() throws IOException {// 准备阶段, 创建出两个队列, 以备后用messageFileManager.createQueueFiles(queueName1);messageFileManager.createQueueFiles(queueName2);
}// 这个方法就是每个用例执行完毕之后的收尾工作
@AfterEach
public void tearDown() throws IOException {// 收尾阶段, 就把刚才的队列给干掉.messageFileManager.destroyQueueFiles(queueName1);messageFileManager.destroyQueueFiles(queueName2);
}

🌲测试创建队列功能

在每个测试用例之前,我们都会进行创建队列

该项测试就是为了测试队列是否创建成功

我们依旧使用断言进行判断

我们只需要查看队列中的文件是否存在就行

@Test
public void testCreateFiles() {// 创建队列文件已经在上面 setUp 阶段执行过了. 此处主要是验证看看文件是否存在.File queueDataFile1 = new File(".data/" + queueName1 + "/queue_data.txt");Assertions.assertEquals(true, queueDataFile1.isFile());File queueStatFile1 = new File(".data/" + queueName1 + "/queue_stat.txt");Assertions.assertEquals(true, queueStatFile1.isFile());File queueDataFile2 = new File(".data/" + queueName1 + "/queue_data.txt");Assertions.assertEquals(true, queueDataFile2.isFile());File queueStatFile2 = new File(".data/" + queueName1 + "/queue_stat.txt");Assertions.assertEquals(true, queueStatFile2.isFile());
}

🌳测试统计文件的读写

首先我们需要构建一个 Stat 的对象,并给其相关属性进行赋值

然后接下来我i们开始调用相关方法,但是呢,关于测试文件的读写,在最初设计的时候我们进行了封装,只准内部使用。

所以这里我们使用反射的方式进行访问

恰好Spring 帮我们 封住好了一个工具类,我们这里直接使用就好

在这里插入图片描述

最后我们只需要读取相应的属性与我们写入的数据进行对比就好

@Test
public void testReadWriteStat() {MessageFileManager.Stat stat = new MessageFileManager.Stat();stat.totalCount = 100;stat.validCount = 50;// 此处就需要使用反射的方式, 来调用 writeStat 和 readStat 了.// Java 原生的反射 API 其实非常难用~~// 此处使用 Spring 帮我们封装好的 反射 的工具类.ReflectionTestUtils.invokeMethod(messageFileManager, "writeStat", queueName1, stat);// 写入完毕之后, 再调用一下读取, 验证读取的结果和写入的数据是一致的.MessageFileManager.Stat newStat = ReflectionTestUtils.invokeMethod(messageFileManager, "readStat", queueName1);Assertions.assertEquals(100, newStat.totalCount);Assertions.assertEquals(50, newStat.validCount);System.out.println("测试 readStat 和 writeStat 完成!");
}

🎋测试将相应消息放入文件中

既然要将消息放入队列中,那么首先我们得

构造出队列与消息

注意:此处构造的队列名一定要是我们前面给出的队列名里的一种,不然找不到相应的文件

然后我们将相应的队列与消息放送到文件里

这时候我们再读统计文件里的消息数目,与自己插入的数目是否一致

我们再读取整个数据,得到一个链表

我们再提取其中的对象,与我们放进去之前的对象进行对比,看是否相等

需要注意的是:比较数组时,我们不能使用 assertEquals了,而是使用assertArrayEquals

实现代码:

@Test
public void testSendMessage() throws IOException, MqException, ClassNotFoundException {// 构造出消息, 并且构造出队列.Message message = createTestMessage("testMessage");// 此处创建的 queue 对象的 name, 不能随便写, 只能用 queueName1 和 queueName2. 需要保证这个队列对象// 对应的目录和文件啥的都存在才行.MSGQueue queue = createTestQueue(queueName1);// 调用发送消息方法messageFileManager.sendMessage(queue, message);// 检查 stat 文件.MessageFileManager.Stat stat = ReflectionTestUtils.invokeMethod(messageFileManager, "readStat", queueName1);Assertions.assertEquals(1, stat.totalCount);Assertions.assertEquals(1, stat.validCount);// 检查 data 文件LinkedList<Message> messages = messageFileManager.loadAllMessageFromQueue(queueName1);Assertions.assertEquals(1, messages.size());Message curMessage = messages.get(0);Assertions.assertEquals(message.getMessageId(), curMessage.getMessageId());Assertions.assertEquals(message.getRoutingKey(), curMessage.getRoutingKey());Assertions.assertEquals(message.getDeliverMode(), curMessage.getDeliverMode());// 比较两个字节数组的内容是否相同, 不能直接使用 assertEquals 了.Assertions.assertArrayEquals(message.getBody(), curMessage.getBody());System.out.println("message: " + curMessage);
}

🎍测试读文件里的消息到内存

这里的测试方法其实与上面类似,构造队列与消息

然后一一去除进行对比,这里我们测试的数据更多

实现代码如下:

@Test
public void testLoadAllMessageFromQueue() throws IOException, MqException, ClassNotFoundException {// 往队列中插入 100 条消息, 然后验证看看这 100 条消息从文件中读取之后, 是否和最初是一致的.MSGQueue queue = createTestQueue(queueName1);List<Message> expectedMessages = new LinkedList<>();for (int i = 0; i < 100; i++) {Message message = createTestMessage("testMessage" + i);messageFileManager.sendMessage(queue, message);expectedMessages.add(message);}// 读取所有消息LinkedList<Message> actualMessages = messageFileManager.loadAllMessageFromQueue(queueName1);Assertions.assertEquals(expectedMessages.size(), actualMessages.size());for (int i = 0; i < expectedMessages.size(); i++) {Message expectedMessage = expectedMessages.get(i);Message actualMessage = actualMessages.get(i);System.out.println("[" + i + "] actualMessage=" + actualMessage);Assertions.assertEquals(expectedMessage.getMessageId(), actualMessage.getMessageId());Assertions.assertEquals(expectedMessage.getRoutingKey(), actualMessage.getRoutingKey());Assertions.assertEquals(expectedMessage.getDeliverMode(), actualMessage.getDeliverMode());Assertions.assertArrayEquals(expectedMessage.getBody(), actualMessage.getBody());Assertions.assertEquals(0x1, actualMessage.getIsValid());}
}

🍀测试删除消息

此时我们的测试思路依旧是构造一些消息写入文件,然后进行删除操作,最后读取剩余文件与写入文件进行对比

这一次我们插入10个消息数据,然后删除后面三个的消息数据

最后读取文件里面的内容,比对读取的消息长度与删除后的长度是否一样

然后再一一对比里面的数据是否一样

实现代码如下:

@Test
public void testDeleteMessage() throws IOException, MqException, ClassNotFoundException {// 创建队列, 写入 10 个消息. 删除其中的几个消息. 再把所有消息读取出来, 判定是否符合预期.MSGQueue queue = createTestQueue(queueName1);List<Message> expectedMessages = new LinkedList<>();for (int i = 0; i < 10; i++) {Message message = createTestMessage("testMessage" + i);messageFileManager.sendMessage(queue, message);expectedMessages.add(message);}// 删除其中的三个消息messageFileManager.deleteMessage(queue, expectedMessages.get(7));messageFileManager.deleteMessage(queue, expectedMessages.get(8));messageFileManager.deleteMessage(queue, expectedMessages.get(9));// 对比这里的内容是否正确.LinkedList<Message> actualMessages = messageFileManager.loadAllMessageFromQueue(queueName1);Assertions.assertEquals(7, actualMessages.size());for (int i = 0; i < actualMessages.size(); i++) {Message expectedMessage = expectedMessages.get(i);Message actualMessage = actualMessages.get(i);System.out.println("[" + i + "] actualMessage=" + actualMessage);Assertions.assertEquals(expectedMessage.getMessageId(), actualMessage.getMessageId());Assertions.assertEquals(expectedMessage.getRoutingKey(), actualMessage.getRoutingKey());Assertions.assertEquals(expectedMessage.getDeliverMode(), actualMessage.getDeliverMode());Assertions.assertArrayEquals(expectedMessage.getBody(), actualMessage.getBody());Assertions.assertEquals(0x1, actualMessage.getIsValid());}
}

😎测试垃圾回收

我们依旧需要进行构造数据

这次我们构造100条信息存入文件中

并记录此时的文件大小

然后我们删除0下标与偶数下标的消息

然后手动调用GC,读文件里面的内容

把之前消息偶数下标的删了, 剩下的就是奇数下标的元素了.

这时候新旧数据下标和的匹配关系就如下所示

  • 新:i = 0 旧 i = 1
  • 新:i = 1 旧 i = 3
  • 新:i = n 旧 i = 2*n + 1

以此我们来进行比对,并对比前后消息的长度

Assertions.assertTrue()方法来判断表达式的真假

执行代码如下:

@Test
public void testGC() throws IOException, MqException, ClassNotFoundException {// 先往队列中写 100 个消息. 获取到文件大小.// 再把 100 个消息中的一半, 都给删除掉(比如把下标为偶数的消息都删除)// 再手动调用 gc 方法, 检测得到的新的文件的大小是否比之前缩小了.MSGQueue queue = createTestQueue(queueName1);List<Message> expectedMessages = new LinkedList<>();for (int i = 0; i < 100; i++) {Message message = createTestMessage("testMessage" + i);messageFileManager.sendMessage(queue, message);expectedMessages.add(message);}// 获取 gc 前的文件大小File beforeGCFile = new File("./data/" + queueName1 + "/queue_data.txt");long beforeGCLength = beforeGCFile.length();// 删除偶数下标的消息for (int i = 0; i < 100; i += 2) {messageFileManager.deleteMessage(queue, expectedMessages.get(i));}// 手动调用 gcmessageFileManager.gc(queue);// 重新读取文件, 验证新的文件的内容是不是和之前的内容匹配LinkedList<Message> actualMessages = messageFileManager.loadAllMessageFromQueue(queueName1);Assertions.assertEquals(50, actualMessages.size());for (int i = 0; i < actualMessages.size(); i++) {// 把之前消息偶数下标的删了, 剩下的就是奇数下标的元素了.// actual 中的 0 对应 expected 的 1// actual 中的 1 对应 expected 的 3// actual 中的 2 对应 expected 的 5// actual 中的 i 对应 expected 的 2 * i + 1Message expectedMessage = expectedMessages.get(2 * i + 1);Message actualMessage = actualMessages.get(i);Assertions.assertEquals(expectedMessage.getMessageId(), actualMessage.getMessageId());Assertions.assertEquals(expectedMessage.getRoutingKey(), actualMessage.getRoutingKey());Assertions.assertEquals(expectedMessage.getDeliverMode(), actualMessage.getDeliverMode());Assertions.assertArrayEquals(expectedMessage.getBody(), actualMessage.getBody());Assertions.assertEquals(0x1, actualMessage.getIsValid());}// 获取新的文件的大小File afterGCFile = new File("./data/" + queueName1 + "/queue_data.txt");long afterGCLength = afterGCFile.length();System.out.println("before: " + beforeGCLength);System.out.println("after: " + afterGCLength);Assertions.assertTrue(beforeGCLength > afterGCLength);
}

⭕总结

关于《【消息队列开发】 测试MessageFileManager(对硬盘中的消息操作)类》就讲解到这儿,感谢大家的支持,欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/277048.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【设计模式】一、设计模式概述

文章目录 一、设计模式概述&#xff08;一&#xff09;设计模式是什么1. 设计模式的定义2. 设计模式的组成要素3、常用设计模式一览表 &#xff08;二&#xff09;设计模式的优点&#xff08;用途&#xff09;※ 本文小结 一、设计模式概述 &#xff08;一&#xff09;设计模式…

复杂网络——半局部中心法

一、概述 由于最近写论文需要使用复杂网络知识中的半局部中心法&#xff0c;但是截止目前来说&#xff0c;网上几乎搜索不到有关的MATLAB程序代码&#xff0c;只有一篇用Python编写的程序&#xff0c;我的电脑中没有python&#xff0c;所以我花费一些时间&#xff0c;利用matla…

基于SpringBoot+Vue交流和分享平台的设计与实现(源码+部署说明+演示视频+源码介绍)

您好&#xff0c;我是码农飞哥&#xff08;wei158556&#xff09;&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。&#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精通…

Day44-sersync企业实时复制实战

Day44-sersync企业实时复制实战 1. sersync实时复制工具介绍1.1 sersync工具简介1.2 sersync特点1.3 sersync图解原理1.4 sersyncrsync实时复制方案项目实践1.4.1 图解项目方案架构及实现原理1.4.2 确保远程数据传输服务部署完成1.4.3 检查当前系统nfs01是否支持inotify实时监控…

008:安装Docker

安装Docker 如果不太熟悉Linux命令&#xff0c;不想学习Linux命令&#xff0c;可以直接看文末NAS面板章节&#xff0c;通过面板&#xff0c;像使用Window一样操作NAS。 一、安装 Docker 1.安装 Docker wget -qO- https://get.docker.com/ | sh2.启动 Docker 服务 sudo sys…

qt vs 编程 字符编码 程序从源码到编译到显示过程中存在的字符编码及隐藏的字符编码转换

理解字符编码&#xff0c;请参考&#xff1a;unicode ucs2 utf16 utf8 ansi GBK GB2312 CSDN博客 了解windows字符显示必须了解locale概念 参考&#xff1a;揭密 Windows 上的各种 locale - 知乎 汉字&#xff08;或者说多字节字符&#xff09;的存放需求&#xff0c;是计算…

K8S CNI

OCI概念 OCI&#xff0c;Open Container Initiative&#xff0c;开放容器标准&#xff0c;是一个轻量级&#xff0c;开放的治理结构&#xff08;项目&#xff09;&#xff0c;在 Linux 基金会的支持下成立&#xff0c;致力于围绕容器格式和运行时创建开放的行业标准。 OCI 项目…

AI智慧校园电子班牌云平台源码

目录 家长端 学校端 电子围栏 亲情通话 课堂答题 移动化管理模式 统一资源管理平台 模板内容智能更换 家校互联 家长端 多场景通话:上学放学联系、紧急遇险求助联系、日常亲情通话关注孩子人身安全:到校离校情况、进入危险区域预警等。 学校端 课堂秩序管理:提高教…

深入浅出:Objective-C中使用MWFeedParser下载豆瓣RSS

摘要 本文旨在介绍如何在Objective-C中使用MWFeedParser库下载豆瓣RSS内容&#xff0c;同时展示如何通过爬虫代理IP技术和多线程提高爬虫的效率和安全性。 背景 随着信息量的激增&#xff0c;爬虫技术成为了获取和处理大量网络数据的重要手段。Objective-C作为一种成熟的编程…

3D地图在BI大屏中的应用实践

前言 随着商业智能的不断发展&#xff0c;数据可视化已成为一项重要工具&#xff0c;有助于用户更好地理解数据和分析结果。其中&#xff0c;3D地图作为一种可视化工具&#xff0c;已经在BI大屏中得到了广泛地应用。 3D地图通过将地理信息与数据相结合&#xff0c;以更加直观…

工具-百度云盘服务-身份认证

目标 通过百度网盘API的方式去获取网盘中的文件&#xff0c;要实现这的第一步就是需要获取网盘的权限。资料(参考) 如果期望应用访问用户的网盘文件&#xff0c;则需要经过用户同意&#xff0c;这个流程被称为“授权”。百度网盘开放平台基于 OAuth2.0 接入授权。OAuth2.0 是…

嵌入式学习第二十七天!(TCP并发模型)

TCP并发模型&#xff1a; 1. TCP多线程模型&#xff1a; 缺点&#xff1a;创建线程会带来资源开销&#xff0c;能够实现的并发量比较有限。 2. IO模型&#xff1a; 1. 阻塞IO&#xff1a; 没有数据到来时&#xff0c;可以让任务挂起&#xff0c;节省CPU资源开销&#xff0c;提…

物理隔离条件下,如何安全高效地进行内外网文件导入导出?

内外网文件导入导出通常指的是在内部网络&#xff08;内网&#xff09;和外部网络&#xff08;外网&#xff09;之间传输文件的过程。这在企业环境中尤其常见&#xff0c;因为内部网络通常包含敏感数据&#xff0c;而外部网络&#xff08;如互联网&#xff09;则允许更广泛的访…

Apache zookeeper kafka 开启SASL安全认证

背景&#xff1a;我之前安装的kafka没有开启安全鉴权&#xff0c;在没有任何凭证的情况下都可以访问kafka。搜了一圈资料&#xff0c;发现有关于sasl、acl相关的&#xff0c;准备试试。 简介 Kafka是一个高吞吐量、分布式的发布-订阅消息系统。Kafka核心模块使用Scala语言开发…

MySql入门教程--MySQL数据库基础操作

꒰˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之处请多多谅解&#xff0c;让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN …

k8s的pod和svc相互访问时网络链路解析

k8s的pod和svc相互访问时网络链路解析 1. k8s环境中pod相互访问1.1. k8s中pod相互访问的整体流程1.2. k8s的相同机器的不同pod相互访问1.3. k8s的不同机器的不同pod相互访问 2. k8s访问svc2.1 nat操作2.2 流量进入到后端pod 3. 疑问和思考3.1 访问pod相互访问为什么不用做nat?…

【InternLM 实战营笔记】基于 InternLM 和 LangChain 搭建MindSpore知识库

InternLM 模型部署 准备环境 拷贝环境 /root/share/install_conda_env_internlm_base.sh InternLM 激活环境 conda activate InternLM 安装依赖 # 升级pip python -m pip install --upgrade pippip install modelscope1.9.5 pip install transformers4.35.2 pip install…

数据结构之单链表

目录 1.问题引入 2.主题介绍 2.1链表的概念和结构 2.2链表的分类 2.3单链表的实现 2.3.1接口实现 2.3.2函数实现 2.3.3函数测试 3.小结 halo&#xff0c;又和大家见面了&#xff0c;今天要给大家分享的是单链表的知识&#xff0c;跟着我的脚步&#xff0c;包学包会哦~ …

中电金信:技术实践|Flink维度表关联方案解析

导语&#xff1a;Flink是一个对有界和无界数据流进行状态计算的分布式处理引擎和框架&#xff0c;主要用来处理流式数据。它既可以处理有界的批量数据集&#xff0c;也可以处理无界的实时流数据&#xff0c;为批处理和流处理提供了统一编程模型。 维度表可以看作是用户来分析数…

人工智能|机器学习——K-means系列聚类算法k-means/ k-modes/ k-prototypes/ ......(划分聚类)

1.k-means聚类 1.1.算法简介 K-Means算法又称K均值算法&#xff0c;属于聚类&#xff08;clustering&#xff09;算法的一种&#xff0c;是应用最广泛的聚类算法之一。所谓聚类&#xff0c;即根据相似性原则&#xff0c;将具有较高相似度的数据对象划分至同一类簇&#xff0c;…