如何在命令行应用中使用Azurite进行Blob单元测试?
在命令行应用/单元测试中按需启动Azurite进行Blob验证
一、程序化启动Azurite(推荐方案)
不用手动命令行启动,直接通过代码控制Azurite的生命周期,从根源避免权限、端口冲突问题。
1. 准备工作
确保已安装Azurite:
- 方式1:使用Visual Studio自带的Azurite,路径一般为
C:\Program Files\Microsoft Visual Studio\2022\<版本>\Common7\IDE\Extensions\Microsoft\Azure Storage Emulator\azurite.exe - 方式2:通过npm全局安装:
npm install -g azurite,安装后可直接用azurite命令调用
2. 代码实现启动/停止Azurite
以下是命令行应用或单元测试中的核心代码:
using System.Diagnostics; using System.Text; using Azure.Storage.Blobs; // 启动Azurite进程 var azuritePath = @"C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\Extensions\Microsoft\Azure Storage Emulator\azurite.exe"; // 若用npm安装,替换为: // var azuritePath = "node"; // var arguments = @"C:\Users\<你的用户名>\AppData\Roaming\npm\node_modules\azurite\dist\src\cli.js --blobHost 127.0.0.1 --blobPort 10002 --location C:\Temp\AzuriteData"; var arguments = "--blobHost 127.0.0.1 --blobPort 10002 --location C:\\Temp\\AzuriteData"; var processStartInfo = new ProcessStartInfo(azuritePath, arguments) { CreateNoWindow = true, UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true }; var azuriteProcess = Process.Start(processStartInfo); // 等待Azurite初始化完成(可根据需要调整等待时间,或用端口监听逻辑替代) await Task.Delay(2000); // 自定义端口的连接字符串 var connectionString = "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10002/devstoreaccount1;"; var blobServiceClient = new BlobServiceClient(connectionString); // 执行Blob创建与验证逻辑 var containerClient = blobServiceClient.GetBlobContainerClient("test-container"); await containerClient.CreateIfNotExistsAsync(); var blobClient = containerClient.GetBlobClient("test-blob.txt"); await blobClient.UploadAsync(new MemoryStream(Encoding.UTF8.GetBytes("Test content")), overwrite: true); // 验证Blob存在 var exists = await blobClient.ExistsAsync(); Debug.Assert(exists, "Blob未创建成功"); // 测试完成后关闭Azurite azuriteProcess.Kill(); await azuriteProcess.WaitForExitAsync(); azuriteProcess.Dispose();
3. 解决权限与端口问题
- EPERM权限错误:
- 指定的
--location路径需选当前用户有写入权限的文件夹(如C:\Temp\AzuriteData),避开系统盘根目录或受保护的文件夹 - 不要用管理员权限启动命令行/应用,反而可能引发权限冲突
- 指定的
- 端口被占用:
- 在启动参数中指定非默认端口(如示例中的10002),避开10000等常用端口
- 启动前可通过
netstat -ano | findstr :10000查看占用进程,手动终止后再启动
二、集成到单元测试(以xUnit为例)
将Azurite的启动/关闭逻辑封装到Fixture中,实现测试类级别的生命周期管理:
using System.Diagnostics; using System.Text; using Azure.Storage.Blobs; using Xunit; public class AzuriteFixture : IAsyncLifetime { private Process _azuriteProcess; public BlobServiceClient BlobServiceClient { get; private set; } public async Task InitializeAsync() { // 启动Azurite var azuritePath = @"C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\Extensions\Microsoft\Azure Storage Emulator\azurite.exe"; var arguments = "--blobHost 127.0.0.1 --blobPort 10002 --location C:\\Temp\\AzuriteData"; var processStartInfo = new ProcessStartInfo(azuritePath, arguments) { CreateNoWindow = true, UseShellExecute = false }; _azuriteProcess = Process.Start(processStartInfo); await Task.Delay(2000); // 初始化Blob客户端 var connectionString = "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10002/devstoreaccount1;"; BlobServiceClient = new BlobServiceClient(connectionString); } public async Task DisposeAsync() { // 清理Azurite进程 if (_azuriteProcess != null && !_azuriteProcess.HasExited) { _azuriteProcess.Kill(); await _azuriteProcess.WaitForExitAsync(); _azuriteProcess.Dispose(); } } } // 使用Fixture的测试类 public class BlobUnitTests : IClassFixture<AzuriteFixture> { private readonly AzuriteFixture _fixture; public BlobUnitTests(AzuriteFixture fixture) { _fixture = fixture; } [Fact] public async Task CreateAndVerifyBlob_Succeeds() { var containerClient = _fixture.BlobServiceClient.GetBlobContainerClient("test-container"); await containerClient.CreateIfNotExistsAsync(); var blobClient = containerClient.GetBlobClient("test-blob.txt"); await blobClient.UploadAsync(new MemoryStream(Encoding.UTF8.GetBytes("Test content")), overwrite: true); var exists = await blobClient.ExistsAsync(); Assert.True(exists); } }
三、替代方案:用Docker启动Azurite
若本地有Docker环境,可直接启动Azurite容器,无需本地安装Azurite:
using System.Diagnostics; using Azure.Storage.Blobs; // 启动Azurite容器 var dockerStartInfo = new ProcessStartInfo("docker", "run -d -p 10002:10000 mcr.microsoft.com/azure-storage/azurite azurite-blob --blobHost 0.0.0.0") { CreateNoWindow = true, UseShellExecute = false, RedirectStandardOutput = true }; var dockerProcess = Process.Start(dockerStartInfo); var containerId = await dockerProcess.StandardOutput.ReadLineAsync(); await Task.Delay(2000); // 使用映射后的端口连接 var connectionString = "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10002/devstoreaccount1;"; var blobServiceClient = new BlobServiceClient(connectionString); // 执行Blob操作... // 停止并删除容器 Process.Start("docker", $"stop {containerId}").WaitForExit(); Process.Start("docker", $"rm {containerId}").WaitForExit();
内容的提问来源于stack exchange,提问作者David Thielen
相关产品推荐
相关产品推荐

