【问题标题】:ASP.NET Web API Test instance initializationASP.NET Web API 测试实例初始化
【发布时间】:2021-08-12 03:25:16
【问题描述】:

我正在为我的 Web API 编写一些集成测试,这意味着它必须在测试执行期间运行。有什么方法可以使用内存数据库而不是基于 SQL Server 的真实数据库来运行它?

另外,我需要一次运行几个实例,所以我需要以某种方式将每个实例的基地址更改为唯一的。例如,我可以将以下代码中提到的这些实例 ID 附加到基本 URL。

这是我用来为我的测试运行一个新实例的代码:

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();
}

总的来说,这是创建测试实例的好方法,还是我遗漏了什么?问这个,因为也许有另一种“合法”的方式来实现我的目标。

【问题讨论】:

  • in-memory database 是什么意思,我可以知道你的意思吗?
  • @MdFaridUddinKiron,我的意思是 DbContext 配置为使用方法 UseInMemoryDatabase();。我知道如何使用它,但我需要以某种方式确定我的 API 实例是通过测试运行还是只是正常启动。
  • 是的,我希望您也可以在您的 startup.cs 文件中确定这一点。
  • 您应该小心使用 InMemoryDatabase。不支持关系、存储过程等SQL特性,也可以使用SQLite。
  • @İbrahimULUDAĞ,谢谢!我不知道。然后我将创建一个临时数据库并在测试完成后将其删除。

标签: c# integration-testing asp.net-core-webapi


【解决方案1】:

好的,所以最后,我想出了这个超级简单明了的解决方案。

正如 cmets 中提到的 - 使用内存数据库并不是测试的最佳方式,因为如果使用 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 测试框架,这意味着我只需要在夹具中实现 Web 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 中查找连接字符串。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-18
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    相关资源
    最近更新 更多