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 中查找连接字符串。

就是这样!希望这可以帮助其他人:)