【消息队列开发】 测试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));
    }

    // 手动调用 gc
    messageFileManager.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 + 1
        Message 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(对硬盘中的消息操作)类》就讲解到这儿,感谢大家的支持,欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

AtomoVideo:AIGC赋能下的电商视频动效生成

✍&#x1f3fb; 本文作者&#xff1a;凌潼、依竹、桅桔、逾溪 1. 概述 当今电商领域&#xff0c;内容营销的形式正日趋多样化&#xff0c;视频内容以其生动鲜明的视觉体验和迅捷高效的信息传播能力&#xff0c;为商家创造了新的机遇。消费者对视频内容的偏好驱动了视频创意供给…

Yolo系列算法-理论部分-YOLOv3

0. 写在前面 YOLO系列博客&#xff0c;紧接上一篇Yolo系列算法-理论部分-YOLOv2-CSDN博客 1. YOLOv3-定型之作 2018年&#xff0c;Redmon团队推出YOLOv3的网络模型&#xff0c;将骨干网络&#xff08;backbone&#xff09;由darknet-19替换成darknet-53网络&#xff0c;加入特…

【Python循环2/5】for循环的复杂应用

目录 序言 导入1 累加 练习 导入2 计数器 练习 导入3 if判断 总结 序言 昨天&#xff0c;我们学习了 for 循环遍历列表、字典等数据的方式。今天我们会学习&#xff0c;for 循环与“累加” 、if 判断和“计数器”的结合运用。 导入1 在前面的学习中&#xff0c;我们学…

计算机网络——物理层(数据交换方式)

计算机网络——数据交换方式 提高数据交换方式的必要性电路交换电路交换原理电路交换的阶段建立阶段通信阶段和连接拆除阶段 电路交换的优缺点报文交换什么是报文报文交换的阶段报文交换的优缺点 分组交换分组交换的阶段分组交换的优缺点 数据交换方式的选择数据报方式数据报方…

VS Code上,QT基于cmake,qmake的构建方法(非常详细)

VS Code上,QT基于cmake&#xff0c;qmake的构建方法 1 前言2 QT基于cmake的构建方法2.1 VS Code关键插件安装2.2 系统环境变量配置2.3 VS Code中&#xff0c;环境变量配置2.4 Cmake新建一个新的Porject 3 QT基于qmake的构建方法 1 前言 最近&#xff0c;由于认证了github的学生…

尺寸小又薄的整流桥IBS

1. 整流桥功能介绍 整流桥在电子领域中扮演着至关重要的角色&#xff0c;为各种电子设备和电路提供了稳定的电源。整流桥的主要作用是将交流电信号转换为直流电信号。当交流电信号通过整流桥时&#xff0c;它会使得只有一个方向的电流能够通过&#xff0c;从而实现了将交流电信…

【数据结构练习题】栈——1.括号匹配 2.逆波兰表达式求值 3.出栈入栈次序匹配 4.最小栈

♥♥♥♥♥个人主页♥♥♥♥♥ ♥♥♥♥♥数据结构练习题总结专栏♥♥♥♥♥ 文件目录 前言1.括号匹配1.1问题描述1.2解题思路1.3画图解释1.4代码实现2.逆波兰表达式求值 2.1问题描述2.2解题思路2.3画图解释2.4代码解释3.出栈入栈次序匹配 3.1问题描述3.2思路分析3.3画图解释3.…

金融知识分享系列之:MACD指标精讲

金融知识分享系列之&#xff1a;MACD指标精讲 一、MACD指标二、指标原理三、MACD指标参考用法四、MACD计算步骤五、MACD分析要素六、根据快线DIF位置判断趋势七、金叉死叉作为多空信号八、快线位置交叉信号九、指标背离判断行情反转十、差离值的正负十一、差离值的变化十二、指…

KBP210-ASEMI新能源专用整流桥KBP210

编辑&#xff1a;ll KBP210-ASEMI新能源专用整流桥KBP210 型号&#xff1a;KBP210 品牌&#xff1a;ASEMI 封装&#xff1a;KBP-4 正向电流&#xff08;Id&#xff09;&#xff1a;2A 反向耐压&#xff08;VRRM&#xff09;&#xff1a;1000V 正向浪涌电流&#xff1a;6…

中整协与成都艺星联合主办的“面部馒化修复注射技术培训班”圆满落下帷幕

在追求医疗美容学科深度的道路上&#xff0c;Yestar成都艺星再次成为行业先锋&#xff0c;近日&#xff0c;由中整协与成都艺星整形美容医院联合主办的“面部馒化修复注射技术培训班”在Yestar成都艺星圆满落下帷幕。本次培训班以其严谨的学术精神和对临床治疗思路的深入解读&a…

在idea中配置tomcat服务器,部署一个项目(下载教程加链接)

第一步&#xff1a;把Tomcat下载好 ww​​​​​​​Apache Tomcat - Welcome! 链接如上&#xff1a;进去后在左边找到Tomcat8点击进去后 找到图下内容 第二步&#xff1a; 打开这个文件点击bin进去 会出现一个黑色框框&#xff0c;也就是服务器 完成后就可以在浏览器输入…

Redis 搭建主从集群

文章目录 1. 主从集群架构1.1 准备实例和配置1.2 启动1.3 开启主从关系1.4 测试 2. 主从同步原理2.1 全量同步2.2 增量同步repl_backlog原理 2.3 主从同步优化小结 单节点的 Redis 并发能力有限&#xff0c;要进一步提高 Redis 的并发能力&#xff0c;就需要搭建主从集群&#…

2024年无人直播是否已经成为新趋势,商家使用矩图AI无人直播月增长5万+

无论是 个体商户、企业经营者、电商从业者、想创业赚钱的朋友;也不管你是做餐饮还是非餐饮;亦或是抖音小时达外卖。这篇文章&#xff0c;请勿必看完&#xff0c;对你的业绩增长是有绝对的帮助。 无人直播的发展经历了几个时代&#xff0c;现在已经到了4.0的时代&#xff0c;更安…

刷题DAY24 | LeetCode 77-组合

1 回溯法理论基础 回溯法也可以叫做回溯搜索法&#xff0c;它是一种搜索的方式。回溯是递归的副产品&#xff0c;只要有递归就会有回溯。 所以以下讲解中&#xff0c;回溯函数也就是递归函数&#xff0c;指的都是一个函数。 1.1 回溯法的效率 回溯法的性能如何呢&#xff0…

深入探索Java并发编程:ArrayBlockingQueue详解

码到三十五 &#xff1a; 个人主页 心中有诗画&#xff0c;指尖舞代码&#xff0c;目光览世界&#xff0c;步履越千山&#xff0c;人间尽值得 ! 在Java的并发编程世界中&#xff0c;java.util.concurrent包为我们提供了多种用于线程间安全通信的数据结构&#xff0c;其中Arra…

PTA冰岛人

作者 陈越 单位 浙江大学 2018年世界杯&#xff0c;冰岛队因1:1平了强大的阿根廷队而一战成名。好事者发现冰岛人的名字后面似乎都有个“松”&#xff08;son&#xff09;&#xff0c;于是有网友科普如下&#xff1a; 冰岛人沿用的是维京人古老的父系姓制&#xff0c;孩子的姓…

【研发日记】Matlab/Simulink技能解锁(二)——在Matlab Function编辑窗口Debug

文章目录 前言 行断点 条件断点 按行步进 Watch Value 分析和应用 总结 前言 见《【研发日记】Matlab/Simulink技能解锁(一)——在Simulink编辑窗口Debug》 行断点 当Matlab Function出现异常时&#xff0c;如果能确定大致的代码段&#xff0c;就可以在相应的行上设置一…

为什么单线程的 Redis 能那么快?

大家好我是苏麟 , 给大家找一些好的文章看看 . 原文文章 : 03 高性能IO模型&#xff1a;为什么单线程Redis能那么快&#xff1f; (lianglianglee.com) Redis 为什么用单线程&#xff1f; 要更好地理解 Redis 为什么用单线程&#xff0c;我们就要先了解多线程的开销。 多线程的…

算法打卡day18|二叉树篇07|Leetcode 530.二叉搜索树的最小绝对差、501.二叉搜索树中的众数、236. 二叉树的最近公共祖先

算法题 Leetcode 530.二叉搜索树的最小绝对差 题目链接:530.二叉搜索树的最小绝对差 大佬视频讲解&#xff1a;二叉搜索树的最小绝对差视频讲解 个人思路 因为是在二叉搜索树求绝对差&#xff0c;而二叉搜索树是有序的&#xff0c;那就把它想成在一个有序数组上求最值&…

CVE-2019-5782:kArgumentsLengthType 设置偏小导致优化阶段可以错误的去除 CheckBound 节点

文章目录 环境搭建漏洞分析笔者初分析笔者再分析漏洞触发源码分析 漏洞利用总结 环境搭建 sudo apt install pythongit reset --hard b474b3102bd4a95eafcdb68e0e44656046132bc9 export DEPOT_TOOLS_UPDATE0 gclient sync -D// debug version tools/dev/v8gen.py x64.debug ni…