System.AggregateException:“一个或多个托管服务未能停止。(操作被取消。)'

Ste*_*eve 7 c# xunit

我正在使用 XUnit 编写集成测试,我的 Web api 代码也在 C# NET 6 和 EF Core 中。

当我调试它时,它可以到达Web api及其服务层。但当它到达 EF Core 上下文查询示例时private Message? GetMessage() => _myContext.Messages.OrderBy(m => m.CreatedUtc).FirstOrDefault();,它会在 处中断Program.cs。

在此输入图像描述

TestingWebAppFactory这是类的代码

public class TestingWebAppFactory<TEntryPoint> : WebApplicationFactory<Program> where TEntryPoint : Program
{
    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder.ConfigureServices(services =>
        {
            var descriptor = services.SingleOrDefault(
                d => d.ServiceType ==
                    typeof(DbContextOptions<MyContext>));

            if (descriptor != null)
                services.Remove(descriptor);

            services.AddDbContext<MyContext>(options =>
            {
                options.UseInMemoryDatabase("myinmemorydb");
            });

            var sp = services.BuildServiceProvider();
            using (var scope = sp.CreateScope())
            using (var appContext = scope.ServiceProvider.GetRequiredService<MyContext>())
            {
                try
                {
                    appContext.Database.EnsureCreated();
                }
                catch (Exception ex)
                {
                    //Log errors or do anything you think it's needed
                    throw;
                }
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我在 Xunit 中的代码

public class MyServiceTest : IClassFixture<TestingWebAppFactory<Program>>
{

    private readonly HttpClient _client;

    public MyServiceTest(TestingWebAppFactory<Program> factory)
    {
        _client = factory.CreateClient();
    }

    [Fact]
    public async Task WhenAValidMessagePosted_ThenShouldReturn()
    {
        CancellationTokenSource source = new CancellationTokenSource();
        CancellationToken token = source.Token;
        source.CancelAfter(TimeSpan.FromSeconds(5));
        var response = await _client.GetAsync("https://localhost:xxxx/api/service/message/post?cronExpresson=0");
    }
}
Run Code Online (Sandbox Code Playgroud)

小智 1

该问题似乎可能与您在测试环境中配置 EF Core 上下文的方式有关。

尝试确保您的测试项目引用 EF Core 和 EF Core 内存数据库所需的 NuGet 包。

验证您的MyContext类是否继承DbContext并正确配置。

更新TestingWebAppFactory类以使用正确的泛型类型参数 ( TEntryPoint) WebApplicationFactory。Program尝试用TEntryPoint这样的方式替换:

public class TestingWebAppFactory<TEntryPoint> : WebApplicationFactory<TEntryPoint> where TEntryPoint : class
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

检查您的MyContext类是否在测试环境中正确注册。在您的TestingWebAppFactory班级中,Program注册. 尝试像这样更新你的方法:TEntryPointDbContextOptions<MyContext>ConfigureWebHost

protected override void ConfigureWebHost(IWebHostBuilder builder)
{
    builder.ConfigureServices(services =>
    {
        var descriptor = services.SingleOrDefault(
            d => d.ServiceType == typeof(DbContextOptions<MyContext>));

        if (descriptor != null)
            services.Remove(descriptor);

        services.AddDbContext<MyContext>(options =>
        {
            options.UseInMemoryDatabase("myinmemorydb");
        });
        
        // ...
    });
}
Run Code Online (Sandbox Code Playgroud)

确保该MyContext实例在您的测试类中得到正确解析。在您的MyServiceTest类中,将TestingWebAppFactory泛型类型参数更新为TEntryPoint如下所示:

public class MyServiceTest : IClassFixture<TestingWebAppFactory<Program>>
{
    private readonly HttpClient _client;

    public MyServiceTest(TestingWebAppFactory<Program> factory)
    {
        _client = factory.CreateClient();
    }

    // ...
}
Run Code Online (Sandbox Code Playgroud)

希望这有帮助!