【问题标题】:Azure DevOps Hosted Build Controller - Is the Azure Storage Emulator supported?Azure DevOps 托管构建控制器 - 是否支持 Azure 存储模拟器?
【发布时间】:2015-11-15 19:13:03
【问题描述】:
我想运行使用 Azure 存储模拟器而不是来自 Azure DevOps 构建的真实存储的单元/集成测试。
模拟器安装在 Hosted Build Controller 上,作为 Azure SDK 的一部分,位于其通常的位置 (C:\Program Files (x86)\Microsoft SDKs\Azure\Storage Emulator\AzureStorageEmulator.exe)。
但是,模拟器在构建控制器上处于未初始化状态。尝试从命令行运行命令Init 时,出现以下错误:
This operation requires an interactive window station
是否有已知的解决方法或计划在 Azure DevOps 构建中支持模拟器?
【问题讨论】:
标签:
azure
azure-devops
azure-sdk-.net
azure-storage-emulator
【解决方案1】:
尽管所有答案都相反,我已经在 VS2017 托管的构建代理上运行 Azure 存储模拟器一年多了。
诀窍是先初始化 SQL LocalDB(模拟器使用它),然后启动模拟器。您可以使用运行的命令行任务来执行此操作:
sqllocaldb create MSSQLLocalDB
sqllocaldb start MSSQLLocalDB
sqllocaldb info MSSQLLocalDB
"C:\Program Files (x86)\Microsoft SDKs\Azure\Storage Emulator\AzureStorageEmulator.exe" start
【解决方案2】:
如前所述,您无法运行 Azure 存储模拟器。您可以运行的是 Azurite 一个开源替代方案。
请注意:Azurite 可以模拟 blob、表和队列。但是我只以这种方式使用了 blob 存储仿真。
在您的构建配置开始时添加一个运行自定义 nuget 命令install Azurite -version 2.2.2 的 nuget 步骤。然后添加一个运行start /b $(Build.SourcesDirectory)\Azurite.2.2.2\tools\blob.exe 的命令行步骤。
它与 Azure 存储模拟器在同一端口上运行,因此您可以使用标准连接字符串。
【解决方案4】:
似乎答案可能来自 Visual Studio Online。如果有人遇到类似问题,可以使用 User Voice 条目。
不太清楚为什么模拟器没有非交互模式,我个人 99% 的时间都不使用它的 UI。有一个通用的 User Voice 条目可让 Azure 存储更易于单元测试。
【解决方案5】:
如果您想直接在 C# 中的集成测试代码中启动 Azure 存储模拟器,您可以将其放入您的测试初始化(启动)代码中(示例适用于 xUnit):
[Collection("Database collection")]
public sealed class IntegrationTests
{
public IntegrationTests(DatabaseFixture fixture)
{
this.fixture = fixture;
}
[Fact]
public async Task TestMethod1()
{
// use fixture.Table to run tests on the Azure Storage
}
private readonly DatabaseFixture fixture;
}
public class DatabaseFixture : IDisposable
{
public DatabaseFixture()
{
StartProcess("SqlLocalDB.exe", "create MSSQLLocalDB");
StartProcess("SqlLocalDB.exe", "start MSSQLLocalDB");
StartProcess("SqlLocalDB.exe", "info MSSQLLocalDB");
StartProcess(EXE_PATH, "start");
var client = CloudStorageAccount.DevelopmentStorageAccount.CreateCloudTableClient();
Table = client.GetTableReference("tablename");
InitAsync().Wait();
}
public void Dispose()
{
Table.DeleteIfExistsAsync().Wait();
StartProcess(EXE_PATH, "stop");
}
private async Task InitAsync()
{
await Table.DeleteIfExistsAsync();
await Table.CreateAsync();
}
static void StartProcess(string path, string arguments, int waitTime = WAIT_FOR_EXIT) =>
Process.Start(path, arguments).WaitForExit(waitTime);
public CloudTable Table { get; }
private const string EXE_PATH =
"C:\\Program Files (x86)\\Microsoft SDKs\\Azure\\Storage Emulator\\AzureStorageEmulator.exe";
private const int WAIT_FOR_EXIT = 60_000;
}
[CollectionDefinition("Database collection")]
public class DatabaseCollection : ICollectionFixture<DatabaseFixture>
{
// This class has no code, and is never created. Its purpose is simply
// to be the place to apply [CollectionDefinition] and all the
// ICollectionFixture<> interfaces.
}