ASP.NET Web API 测试实例初始化
ASP.NET Web API Test instance initialization
我正在为我的网站 API 编写一些集成测试,这意味着在测试执行期间它必须 运行ning。有什么方法可以 运行 使用内存数据库而不是基于 SQL 服务器的真实数据库吗?
此外,我需要一次 运行 几个实例,所以我需要以某种方式将每个实例的基地址更改为唯一。例如,我可以将这些实例 ID 附加到基础 URL,这些实例 ID 在下面的代码中提到。
这是我用来 运行 我的测试新实例的代码:
public static class WebApiHelper
{
private const string ExecutableFileExtension = "exe";
private static readonly Dictionary<Guid, Process> _instances = new();
public static void EnsureIsRunning(Assembly? assembly, Guid instanceId)
{
if (assembly is null)
throw new ArgumentNullException(nameof(assembly));
var executableFullName = Path.ChangeExtension(
assembly.Location, ExecutableFileExtension);
_instances.Add(instanceId, Process.Start(executableFullName));
}
public static void EnsureIsNotRunning(Guid instaceId)
=> _instances[instaceId].Kill();
}
总的来说,这是创建测试实例的好方法,还是我遗漏了什么?问这个问题,因为也许还有另一种 'legal' 方法可以实现我的目标。
好吧,最后,我想到了这个超级简单明了的解决方案。
如评论中所述 - 使用内存数据库不是最佳测试方法,因为如果使用 MS SQL,则不支持关系功能。
所以我决定走另一条路。
第 1 步:覆盖连接字符串。
在我的例子中,这很容易,因为我有一个静态 IConfiguration 实例,只需要覆盖该实例中的连接字符串。
方法如下所示:
private const string ConnectionStringsSectionName = "ConnectionStrings";
private const string TestConnectionStringFormat = "{0}_Test";
private static bool _connectionStringsOverwitten;
private static void OverwriteConnectionStrings()
{
if (_connectionStringsOverwitten)
return;
var connectionStrings = MyStaticConfigurationContainer.Configuration
.AsEnumerable()
.Where(entry => entry.Key.StartsWith(ConnectionStringsSectionName)
&& entry.Value is not null);
foreach (var connectionString in connectionStrings)
{
var builder = new SqlConnectionStringBuilder(connectionString.Value);
builder.InitialCatalog = string.Format(TestConnectionStringFormat,
builder.InitialCatalog);
MyStaticConfigurationContainer.Configuration[connectionString.Key] = builder.ConnectionString;
}
_connectionStringsOverwitten = true;
}
当然,您需要在 运行测试之前和之后处理数据库的创建和删除,否则 - 您的测试数据库可能会变得一团糟。
第 2 步:只需 运行 您的 Web API 实例在一个单独的线程中。
在我的例子中,我使用的是 NUnit 测试框架,这意味着我只需要在夹具中实现网络 API 设置逻辑。基本上,每个测试框架的过程或多或少都是相同的。
代码如下所示:
[SetUpFixture]
public class WebApiSetupFixture
{
private const string WebApiThreadName = "WebApi";
[OneTimeSetUp]
public void SetUp() => new Thread(RunWebApi)
{
Name = WebApiThreadName
}.Start();
private static void RunWebApi()
=> Program.Main(Array.Empty<string>());
// 'Program' - your main web app class with entry point.
}
注意:Program.Main();
中的代码还将在上一步中更改的 MyStaticConfigurationContainer.Configuration
中查找连接字符串。
就是这样!希望这可以帮助其他人:)
我正在为我的网站 API 编写一些集成测试,这意味着在测试执行期间它必须 运行ning。有什么方法可以 运行 使用内存数据库而不是基于 SQL 服务器的真实数据库吗?
此外,我需要一次 运行 几个实例,所以我需要以某种方式将每个实例的基地址更改为唯一。例如,我可以将这些实例 ID 附加到基础 URL,这些实例 ID 在下面的代码中提到。
这是我用来 运行 我的测试新实例的代码:
public static class WebApiHelper
{
private const string ExecutableFileExtension = "exe";
private static readonly Dictionary<Guid, Process> _instances = new();
public static void EnsureIsRunning(Assembly? assembly, Guid instanceId)
{
if (assembly is null)
throw new ArgumentNullException(nameof(assembly));
var executableFullName = Path.ChangeExtension(
assembly.Location, ExecutableFileExtension);
_instances.Add(instanceId, Process.Start(executableFullName));
}
public static void EnsureIsNotRunning(Guid instaceId)
=> _instances[instaceId].Kill();
}
总的来说,这是创建测试实例的好方法,还是我遗漏了什么?问这个问题,因为也许还有另一种 'legal' 方法可以实现我的目标。
好吧,最后,我想到了这个超级简单明了的解决方案。
如评论中所述 - 使用内存数据库不是最佳测试方法,因为如果使用 MS SQL,则不支持关系功能。 所以我决定走另一条路。
第 1 步:覆盖连接字符串。
在我的例子中,这很容易,因为我有一个静态 IConfiguration 实例,只需要覆盖该实例中的连接字符串。
方法如下所示:
private const string ConnectionStringsSectionName = "ConnectionStrings";
private const string TestConnectionStringFormat = "{0}_Test";
private static bool _connectionStringsOverwitten;
private static void OverwriteConnectionStrings()
{
if (_connectionStringsOverwitten)
return;
var connectionStrings = MyStaticConfigurationContainer.Configuration
.AsEnumerable()
.Where(entry => entry.Key.StartsWith(ConnectionStringsSectionName)
&& entry.Value is not null);
foreach (var connectionString in connectionStrings)
{
var builder = new SqlConnectionStringBuilder(connectionString.Value);
builder.InitialCatalog = string.Format(TestConnectionStringFormat,
builder.InitialCatalog);
MyStaticConfigurationContainer.Configuration[connectionString.Key] = builder.ConnectionString;
}
_connectionStringsOverwitten = true;
}
当然,您需要在 运行测试之前和之后处理数据库的创建和删除,否则 - 您的测试数据库可能会变得一团糟。
第 2 步:只需 运行 您的 Web API 实例在一个单独的线程中。
在我的例子中,我使用的是 NUnit 测试框架,这意味着我只需要在夹具中实现网络 API 设置逻辑。基本上,每个测试框架的过程或多或少都是相同的。
代码如下所示:
[SetUpFixture]
public class WebApiSetupFixture
{
private const string WebApiThreadName = "WebApi";
[OneTimeSetUp]
public void SetUp() => new Thread(RunWebApi)
{
Name = WebApiThreadName
}.Start();
private static void RunWebApi()
=> Program.Main(Array.Empty<string>());
// 'Program' - your main web app class with entry point.
}
注意:Program.Main();
中的代码还将在上一步中更改的 MyStaticConfigurationContainer.Configuration
中查找连接字符串。
就是这样!希望这可以帮助其他人:)