import unittest import os import tempfile import hashlib from datetime import datetime from utils.minio_agent import MinIOAgent # 导入之前的MinIO操作类 class TestMinIOAgent(unittest.TestCase): # 测试配置 - 本地MinIO社区版 MINIO_CONFIG = { 'endpoint': '127.0.0.1:9005', 'access_key': 'admin', # 默认账号 'secret_key': 'abc88888888', # 默认密码 'secure': False # 社区版默认不启用SSL } @classmethod def setUpClass(cls): """初始化测试环境""" # 创建唯一测试桶(避免冲突) timestamp = datetime.now().strftime("%Y%m%d%H%M%S") cls.test_bucket = f"test-bucket-{timestamp}" cls.test_object = "test-data/sample.txt" cls.test_content = b"this is MinIO test data: 1234567890" # 初始化客户端 cls.minio_agent = MinIOAgent(cls.MINIO_CONFIG) # 确保测试桶存在 cls.minio_agent.create_bucket(cls.test_bucket) @classmethod def tearDownClass(cls): """清理测试环境""" try: # 列出并删除桶内所有对象 objects = cls.minio_agent.list_objects(cls.test_bucket) for obj in objects: cls.minio_agent.delete_object(cls.test_bucket, obj['object_name']) # 删除测试桶(MinIO要求桶为空才能删除) cls.minio_agent._client.remove_bucket(cls.test_bucket) print(f"\n测试清理完成,已删除桶: {cls.test_bucket}") except Exception as e: print(f"清理测试环境失败: {str(e)}") def test_01_create_bucket(self): """测试创建存储桶""" new_bucket = f"temp-bucket-{datetime.now().microsecond}" result = self.minio_agent.create_bucket(new_bucket) self.assertTrue(result, "存储桶创建失败") # 验证桶是否存在 exists = self.minio_agent._client.bucket_exists(new_bucket) self.assertTrue(exists, "存储桶创建后未检测到存在") # 清理临时桶 self.minio_agent._client.remove_bucket(new_bucket) def test_02_upload_download(self): """测试上传与下载功能""" # 上传数据 upload_meta = self.minio_agent.upload_bytes( bucket=self.test_bucket, object_name=self.test_object, data=self.test_content ) # 验证上传结果 self.assertEqual(upload_meta['size'], len(self.test_content), "上传数据大小不匹配") self.assertEqual(upload_meta['local_hash'], hashlib.md5(self.test_content).hexdigest(), "本地哈希校验失败") # 下载数据到临时文件 with tempfile.NamedTemporaryFile(delete=False) as temp_file: temp_path = temp_file.name download_meta = self.minio_agent.download_file( bucket=self.test_bucket, object_name=self.test_object, local_path=temp_path ) # 验证下载内容 with open(temp_path, 'rb') as f: downloaded_content = f.read() self.assertEqual(downloaded_content, self.test_content, "下载数据与原始数据不匹配") self.assertEqual(download_meta['size'], len(self.test_content), "下载文件大小不匹配") # 清理临时文件 os.unlink(temp_path) def test_03_presigned_url(self): """测试生成预签名URL""" # 先上传测试文件 self.minio_agent.upload_bytes( self.test_bucket, self.test_object, self.test_content ) # 生成URL(有效期30秒) url_info = self.minio_agent.get_presigned_url( bucket=self.test_bucket, object_name=self.test_object, expires=30 ) # 验证URL格式 self.assertIn("http://127.0.0.1:9005", url_info['presigned_url'], "预签名URL格式不正确") self.assertEqual(url_info['expires_in'], 30, "过期时间设置不正确") def test_04_list_objects(self): """测试列出对象功能""" # 上传多个测试对象 test_objects = [ "test-folder/file1.txt", "test-folder/file2.csv", "another-folder/image.jpg" ] for obj in test_objects: self.minio_agent.upload_bytes( self.test_bucket, obj, b"tese_list_obj" ) # 列出所有对象 all_objects = self.minio_agent.list_objects(self.test_bucket) self.assertEqual(len(all_objects), len(test_objects) + 1, "列出对象数量不匹配") # +1是之前的test_object # 按前缀筛选 filtered_objects = self.minio_agent.list_objects( self.test_bucket, prefix="test-folder/" ) self.assertEqual(len(filtered_objects), 2, "按前缀筛选结果不正确") def test_05_delete_object(self): """测试删除对象功能""" # 创建测试对象 delete_obj = "to-delete/temp.txt" self.minio_agent.upload_bytes( self.test_bucket, delete_obj, b"will be delete" ) # 执行删除 result = self.minio_agent.delete_object(self.test_bucket, delete_obj) self.assertTrue(result, "删除对象失败") # 验证删除 objects = self.minio_agent.list_objects(self.test_bucket, prefix="to-delete/") self.assertEqual(len(objects), 0, "对象删除后仍存在") def test_06_upload_empty_data(self): """测试上传空数据的异常处理""" with self.assertRaises(ValueError, msg="未捕获空数据上传异常"): self.minio_agent.upload_bytes( self.test_bucket, "empty.txt", b"" ) if __name__ == "__main__": # 执行测试并显示详细结果 unittest.main(verbosity=2)