ASP.NET Core 测试 - 没有方法 'public static IHostBuilder CreateHostBuilder(string[] args)

tez*_*zly 9 c# testing asp.net-core

我正在尝试在测试中设置我的应用程序并在Startup's Configure方法中使用,context.Database.EnsureCreated()并且期望Sqlite文件出现在Test'sbin 文件夹中

这是我的代码:

using Microsoft.AspNetCore.Mvc.Testing;
using System.Threading.Tasks;
using Xunit;

namespace MyApp.Tests
{
    public class UnitTest1 : IClassFixture<CustomWebApplicationFactory<FakeStartup>>
    {
        private readonly CustomWebApplicationFactory<FakeStartup> _factory;

        public UnitTest1(CustomWebApplicationFactory<FakeStartup> factory)
        {
            _factory = factory;
        }

        [Fact]
        public async Task Test1()
        {
            // Arrange
            var client = _factory.CreateClient();

            // Act
            var response = await client.GetAsync("https://localhost:5001/");

            // Assert
            response.EnsureSuccessStatusCode(); // Status Code 200-299
            Assert.Equal("text/html; charset=utf-8", response.Content.Headers.ContentType.ToString());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

正在使用 WebAppFactory:

using MyApp.Tests;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;

public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup : class
{
    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder.UseStartup<FakeStartup>();
    }
}
Run Code Online (Sandbox Code Playgroud)

FakeStartup 在哪里:

using MyApp.Database;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;

namespace MyApp.Tests
{
    public class FakeStartup
    {
        public FakeStartup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {            
            services.AddControllers();

            services.AddDbContext<Context>(x => x.UseSqlite($"filename={Guid.NewGuid():N}.db"));

            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "Test API", Version = "v1" });
            });
        }
    }

    public static void Configure(IApplicationBuilder app, IWebHostEnvironment env, Context context)
    {
        context.Database.EnsureDeleted();
        context.Database.EnsureCreated();

        app.UseSwagger();
        app.UseSwaggerUI(c =>
        {
            c.SwaggerEndpoint("/swagger/v1/swagger.json", "Test API v1");
            c.RoutePrefix = string.Empty;
        });

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseForwardedHeaders(new ForwardedHeadersOptions
        {
            ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
        });

        app.UseAuthentication();

        app.UseCors(x =>
        {
            x.AllowAnyOrigin();
            x.AllowAnyMethod();
            x.AllowAnyHeader();
        });

        app.UseHttpsRedirection();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

问题来了

  Message: 
    System.InvalidOperationException : No method 'public static IHostBuilder CreateHostBuilder(string[] args)' or 'public static IWebHostBuilder CreateWebHostBuilder(string[] args)' found on 'AutoGeneratedProgram'. Alternatively, WebApplicationFactory`1 can be extended and 'CreateHostBuilder' or 'CreateWebHostBuilder' can be overridden to provide your own instance.
  Stack Trace: 
    WebApplicationFactory`1.CreateWebHostBuilder()
    WebApplicationFactory`1.EnsureServer()
    WebApplicationFactory`1.CreateDefaultClient(DelegatingHandler[] handlers)
    WebApplicationFactory`1.CreateDefaultClient(Uri baseAddress, DelegatingHandler[] handlers)
    WebApplicationFactory`1.CreateClient(WebApplicationFactoryClientOptions options)
    WebApplicationFactory`1.CreateClient()
    UnitTest1.Test1() line 20
    --- End of stack trace from previous location where exception was thrown
Run Code Online (Sandbox Code Playgroud)

什么可能导致这种情况?提前致谢

tez*_*zly 23

解决方案:

CustomWebApplicationFactory这种方式创建

public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup : class
{
    protected override IHostBuilder CreateHostBuilder()
    {
        var builder = Host.CreateDefaultBuilder()
                          .ConfigureWebHostDefaults(x =>
                          {
                              x.UseStartup<FakeStartup>().UseTestServer();
                          });
        return builder;
    }
}
Run Code Online (Sandbox Code Playgroud)

在这里找到:

https://thecodebuzz.com/no-method-public-static-ihostbuilder-createhostbuilder/