带有通用IHostBuilder的.Net核心集成TestServer

时间:2019-02-20 18:04:14

标签: c# asp.net-core .net-core xunit asp.net-core-3.0

我已经使用 .Net Core 3.0预览版2 更新了我的网站,并希望使用TestServer进行集成测试。在.Net Core 2.2中,我已经能够使用WebApplicationFactory<Startup>

由于WebHostBuilder将被弃用(有关更多详细信息,请参见(https://docs.microsoft.com/en-us/aspnet/core/migration/22-to-30?view=aspnetcore-2.2&tabs=visual-studio)。我想立即跟进并实现新的通用HostBuilder。它非常适合启动网站,但是在我启动集成测试时会崩溃。我知道WebApplicationFactory确实使用了WebHostBuilder,这就是它崩溃的原因,但是我不知道如何为通用HostBuilder进行更改。

这是我在.Net Core 2.2中运行的代码:

namespace CompX.FunctionalTest.Web.Factory
{
    public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<Startup>
    {
        protected override void ConfigureWebHost(IWebHostBuilder builder)
        {
            builder.ConfigureServices(services =>
            {
                // Create a new service provider.
                var serviceProvider = new ServiceCollection()
                    .AddEntityFrameworkInMemoryDatabase()
                    .BuildServiceProvider();

                // Add a database context (ApplicationDbContext) using an in-memory 
                // database for testing.
                services.AddDbContext<ApplicationDbContext>(options =>
                {
                    options.UseInMemoryDatabase("InMemoryDbForTesting");
                    options.UseInternalServiceProvider(serviceProvider);
                });

                services.AddDbContext<AppIdentityDbContext>(options =>
                {
                    options.UseInMemoryDatabase("Identity");
                    options.UseInternalServiceProvider(serviceProvider);
                });

                services.AddIdentity<ApplicationUser, IdentityRole>()
                        .AddEntityFrameworkStores<AppIdentityDbContext>()
                        .AddDefaultTokenProviders();

                // Build the service provider.
                var sp = services.BuildServiceProvider();

                // Create a scope to obtain a reference to the database
                // context (ApplicationDbContext).
                using (var scope = sp.CreateScope())
                {
                    var scopedServices = scope.ServiceProvider;
                    var db = scopedServices.GetRequiredService<ApplicationDbContext>();
                    var loggerFactory = scopedServices.GetRequiredService<ILoggerFactory>();

                    var logger = scopedServices.GetRequiredService<ILogger<CustomWebApplicationFactory<TStartup>>>();

                    // Ensure the database is created.
                    db.Database.EnsureCreated();

                    try
                    {
                        // Seed the database with test data.
                        var userManager = scopedServices.GetRequiredService<UserManager<ApplicationUser>>();
                        AppIdentityDbContextSeed.SeedAsync(userManager).GetAwaiter().GetResult();
                    }
                    catch (Exception ex)
                    {
                        logger.LogError(ex, $"An error occurred seeding the database with test messages. Error: {ex.Message}");
                    }
                }
            });
        }
    }
}

我尝试使用TestServers中的Microsoft.AspNetCore.TestHost,但它需要new WebHostBuilder()作为参数。

我也尝试将其作为参数传递,但效果不佳:

Host.CreateDefaultBuilder(args)
    .ConfigureWebHostDefaults(webBuilder =>
    {
        webBuilder.UseStartup<Startup>();
    });

找不到.ConfigureWebHostDefaults()函数。

有人成功地在.Net Core 3.0中实现了测试服务器吗? 非常感谢!

PS:我对.Net Core有点陌生

编辑:

这是我从尝试制作新服务器的所有方法中得到的错误: enter image description here

这里是program.cs

namespace CompX.Web
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
}

这是我在github上创建的问题: https://github.com/aspnet/AspNetCore/issues/7754

1 个答案:

答案 0 :(得分:2)

我终于在3.0中获得了实现方法。 这是针对需要解决方案的任何人的完整演练:

  1. 您需要至少具有 .Net Core 3.0.0-preview2 ,因为他们在此预览中添加了WebApplicationFactoryIHostbuilder({{3} }。您可以在这里找到它:https://github.com/aspnet/AspNetCore/pull/6585

  2. 至少将这些软件包升级到版本3.0.0(https://dotnet.microsoft.com/download/dotnet-core/3.0https://github.com/aspnet/AspNetCore/issues/3756):

    • Microsoft.AspNetCore.App Version=3.0.0-preview-19075-0444
    • Microsoft.AspNetCore.Mvc.Testing Version= 3.0.0-preview-19075-0444
    • Microsoft.Extensions.Hosting Version=3.0.0-preview.19074.2
  3. 现在删除Microsoft.AspNetCore.App中已弃用的软件包:

    • Microsoft.AspNetCore Version=2.2.0
    • Microsoft.AspNetCore.CookiePolicy Version=2.2.0
    • Microsoft.AspNetCore.HttpsPolicy Version=2.2.0
    • Microsoft.AspNetCore.Identity Version=2.2.0
  4. 如果您在services.AddIdentity构建器中使用WebApplicationFactory<Startup>,则需要将其删除。否则,您将收到一个新错误,表明您已经Identity.Application已使用该方案。看来新的WebApplicationFactory现在正在使用Startup.cs中的那个。

我别无其他修改。 希望对某些人有帮助!

更新:

在我不得不使用另一个Integration C#文件(例如LoginTest.csManageTest.cs)之前,它一直运行良好。问题是,当我运行测试时,它将无限循环直到我按CTRL +C。 之后,它将显示访问被拒绝错误。

再一次,我不得不从我的WebApplicationFactory中删除种子:

            try
            {
                // Seed the database with test data.
                var userManager = scopedServices.GetRequiredService<UserManager<ApplicationUser>>();
                AppIdentityDbContextSeed.SeedAsync(userManager).GetAwaiter().GetResult();
            }
            catch (Exception ex)
            {
                logger.LogError(ex, $"An error occurred seeding the database with test messages. Error: {ex.Message}");
            }

似乎新的WebApplicationFactory试图为每个工厂重新创建用户管理器。我用Guid.NewGuid()替换了种子用户帐户。

花点时间找出答案。希望它能再次帮助某人。