【消息队列开发】 测试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.mzph.cn/news/748757.shtml

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

相关文章

MySQL行锁核心知识介绍

MySQL的行锁是数据库中用于控制并发访问的一种机制。它允许在数据库的行级别上实现锁定&#xff0c;从而允许多个事务同时修改不同行的数据&#xff0c;而不会相互干扰。这种锁机制可以提高数据库的并发性能&#xff0c;减少锁争用&#xff0c;提高事务的吞吐量。在本教程中&am…

电视盒子解析安装包失败,安卓4.4安装不了kodi的解决方法,如何安装kodi

有些安卓电视或者电视盒子的安卓系统版本太低、自身架构或者屏蔽了安装其他应用的功能&#xff0c;下载的Kodi apk安装包提示无法安装&#xff0c;解析程序包时出现问题、解析出错无法安装、[INSTALL_FAILED_OLDER_SDK]、此应用与您的电视不兼容。 解决方法&#xff1a; 1、3…

OFDM调制解调过程

OFDM&#xff1a; Orthogonal Frequency Division Multiplexing 正交频分复用 1、OFDMA处理流程图 2、QPSK星座图和映射关系 QPSK&#xff08;Quadrature Phase Shift Keying&#xff0c;正交相移键控&#xff09;四相相移调制是利用载波的四种不同相位差来表征输入的…

服务器数据恢复—服务器硬盘灯显示红色的数据恢复案例

服务器数据恢复环境&故障&#xff1a; 一台服务器中有一组由多块硬盘组建的raid阵列&#xff0c;在运行过程中服务器突然崩溃&#xff0c;管理员检查服务器发现该服务器raid阵列中有两块硬盘的指示灯显示红色。于是&#xff0c;管理员重启服务器&#xff0c;服务器重启后&a…

大规模自动化重构框架--OpenRewrite浅析

目录 1. OpenRewrite是什么&#xff1f;定位&#xff1f; 2. OpenWrite具体如何做&#xff1f; 3. 核心概念释义 3.1 Lossless Semantic Trees (LST) 无损语义树 3.2 访问器&#xff08;Visitors&#xff09; 3.3 配方&#xff08;Recipes&#xff09; 4. 参考链接 Open…

PHP爬虫技术:利用simple_html_dom库分析汽车之家电动车参数

摘要/导言 本文旨在介绍如何利用PHP中的simple_html_dom库结合爬虫代理IP技术来高效采集和分析汽车之家网站的电动车参数。通过实际示例和详细说明&#xff0c;读者将了解如何实现数据分析和爬虫技术的结合应用&#xff0c;从而更好地理解和应用相关技术。 背景/引言 随着电…

IO流(3)-文件字符输入\输出流

FIleReader(文件字符输入流&#xff09; 文件字符输出流代码示例 package com.zz.io;import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.Reader;public class Test4 {public static void main(String args[]) …

pycharm @NotNull parameter ‘module‘ of ...

下载了最新pycharm &#xff0c;无法启动运行 pycharm或者idea中Run/Debug Python项目报错 Argument for NotNull parameter ‘module‘ of … 解决方案 删除项目根目录的 idea 文件夹 随后重启&#xff0c;重新配置即可

LIN API call LINWakeup() ignored! due to LIN Interactive Master seetings!

在写使用CANoe写测试用例时&#xff0c;想控制LIN节点的休眠和唤醒&#xff0c;笔者想想这玩意再简单不过了&#xff0c;不过就是调用linWakeup()和linGotoSleep()嘛&#xff0c;可是越自信&#xff0c;现实总会给你啪啪啪打脸。实际写完验证并不能达到效果&#xff0c;看了下w…

WRF模型运行教程(ububtu系统)--III.运行WRF模型(官网案例)

零、创建DATA目录 # 1.创建一个DATA目录用于存放数据&#xff08;一般为fnl数据&#xff0c;放在Build_WRF目录下&#xff09;。 mkdir DATA # 2.进入 DATA cd DATA 一、WPS预处理 在模拟之前先确定模拟域&#xff08;即模拟范围&#xff09;,并进行数据预处理&#xff08…

Docker 哲学 - 容器操作

容器&#xff1a; 创建 停止 删除 强制删除&#xff08;正在运行&#xff09; run stop rm rm -f 列出本地容器&#xff1a; docker ps / docker container ls 镜像&#xff1a; search pull run &#xff1a; …

Altium Designer怎么设置默认原理图纸张大小

Altium Designer怎么设置默认原理图纸张大小 绘制原理图时我们需要设置好原理图图纸大小&#xff0c;建议大家可以将默认原理图图纸设置为A3&#xff0c;A3图纸大小可以容纳下大部分原理图&#xff0c;这样就不用每次画原理图前去修改图纸大小&#xff0c;可以提高设计效率。 …

java serlvet 高校学生画像平台系统Myeclipse开发mysql数据库web结构java编程计算机网页项目echarts图形展现

一、源码特点 java serlvet 高校学生画像平台系统是一套完善的java web信息管理系统 系统采用serlvetdaobean 模式开发本系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCA…

sqllab第三关通关笔记

知识点&#xff1a; 通过回显的信息判断原始语句的组成猜测该语句为 select 1,2,3 from 表名 where id (输入) limit 0,1 首先通过测试判断存在什么类型的sql注入 构造id1/0 发现正常输出&#xff1b;说明是字符型的sql注入 好了&#xff0c;下面就测试有什么限制条件 构造…

AI视频矩阵混剪系统|罐头鱼AI批量混剪定时发送

AI视频矩阵混剪系统&#xff1a;智能创作与发布的完美结合 随着社交媒体平台的快速发展&#xff0c;视频已成为各行业推广和传播的热门方式。然而&#xff0c;对于许多人来说&#xff0c;制作高质量的视频仍然是一项挑战。Q:290615413但现在&#xff0c;有了AI视频矩阵混剪系统…

吴恩达深度学习笔记:神经网络的编程基础2.5-2.8

目录 第一门课&#xff1a;神经网络和深度学习 (Neural Networks and Deep Learning)第二周&#xff1a;神经网络的编程基础 (Basics of Neural Network programming)2.5 导数&#xff08;Derivatives&#xff09;2.6 更多的导数例子&#xff08;More Derivative Examples&…

【快捷部署】002_Flink(1.17.2)

&#x1f4e3;【快捷部署系列】002期信息 编号选型版本操作系统部署形式部署模式002Flink1.17.2CentOS 7.Xtgz包单机 &#x1f449; 演示视频 Flink一键安装&#xff08;本地模式&#xff09; install-flink.sh 脚本内容 #!/bin/bash ####变量 ###执行脚本的当前目录 mydir$…

【linux】搜索所有目录和子目录下的包含.git的文件并删除

一、linux命令搜索所有目录和子目录下的包含.git的文件 在Linux系统中&#xff0c;要搜索所有目录和子目录下的包含.git的文件&#xff0c;可以使用find命令。find命令允许指定路径、表达式和操作来查找文件。 以下是使用find命令搜索包含.git的文件的方法&#xff1a; 1. 基…

oracle基础-子查询 备份

一、什么是子查询 子查询是在SQL语句内的另外一条select语句&#xff0c;也被称为内查询活着内select语句。在select、insert、update、delete命令中允许是一个表达式的地方都可以包含子查询&#xff0c;子查询也可以包含在另一个子查询中。 【例1.1】在Scott模式下&#xff0…

JVM理解学习

参考视频 运行时数据区 JVM架构总览图 绿色的&#xff1a;方法区&#xff0c;堆&#xff0c;是所有线程共享的 黄色的&#xff1a; 虚拟机栈&#xff0c;本地方法栈&#xff0c;程序计数器&#xff0c;是线程私有的 程序计数器 程序计数器是一块较小的内存空间&#xff0c;物…