繁体   English   中英

.net core 3.0,IClassFixture 问题,“未解析的构造函数参数:ITestOutputHelper 输出”

[英].net core 3.0, issue with IClassFixture, "unresolved constructor arguments: ITestOutputHelper output"

我为集成测试升级到 .net core 3.0 的问题制作了一个 repo: https : //github.com/ranouf/TestingWithDotNetCore3_0

当我启动测试时,我遇到了这个问题:消息:

System.AggregateException :发生一个或多个错误。 (类夹具类型“MyIntegrationTests.TestServerFixture”有一个或多个未解析的构造函数参数:ITestOutputHelper 输出)(以下构造函数参数没有匹配的夹具数据:TestServerFixture testServerFixture)----类夹具类型“MyIntegrationTests.TestServerFixture”有一个或更多未解析的构造函数参数: ITestOutputHelper 输出 ---- 以下构造函数参数没有匹配的夹具数据: TestServerFixture testServerFixture Stack Trace: ----- 内部堆栈跟踪 #1 (Xunit.Sdk.TestClassException) ----- - ---- 内部堆栈跟踪 #2 (Xunit.Sdk.TestClassException) -----

这是构造函数:

public class WeatherForecastController_Tests : IClassFixture<TestServerFixture>
{
    public WeatherForecastController_Tests(TestServerFixture testServerFixture, ITestOutputHelper output)
    {
        Client = testServerFixture.Client;
        Output = output;
    }

测试启动:

public class TestStartup : Startup
{
    public TestStartup(IConfiguration configuration)
        : base(configuration)
    {

    }

    public override void SetUpDataBase(IServiceCollection services)
    {
        // here is where I use the InMemoryDatabase 
    }
}

测试服务器夹具:

public class TestServerFixture : WebApplicationFactory<TestStartup>
{
    private IHost _host;
    public HttpClient Client { get; }
    public ITestOutputHelper Output { get; }

    public TestServerFixture(ITestOutputHelper output)
    {
        Output = output;
        Client = Server.CreateClient();
    }

    // never called but this is where i was previously building up the server
    //
    protected override TestServer CreateServer(IWebHostBuilder builder)
    {
        return base.CreateServer(builder);
    }

    protected override IHost CreateHost(IHostBuilder builder)
    {
        _host = builder.Build();

        using (var scope = _host.Services.CreateScope())
        {
            var services = scope.ServiceProvider;
            InitializeDataBase(services, Output);
        }

        _host.Start();
        return _host;
    }

    protected override IHostBuilder CreateHostBuilder() =>
        Host.CreateDefaultBuilder()
            .ConfigureLogging((hostingContext, builder) =>
            {
                builder.Services.AddSingleton<ILoggerProvider>(new XunitLoggerProvider(Output));
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseTestServer();
            });

    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder.UseStartup<TestStartup>();
    }

    private void InitializeDataBase(IServiceProvider services, ITestOutputHelper output)
    {
        try
        {
            output.WriteLine("Starting the database initialization.");
            //here is where is feed the Test DB
            output.WriteLine("The database initialization has been done.");
        }
        catch (Exception ex)
        {
            output.WriteLine("An error occurred while initialization the database.");
            Console.WriteLine(ex.Message);
        }
    }
}

很明显,TestServerFixture testServerFixture 和 ITestOutputHelper 输出的 Iod 不起作用。 如何使它工作?

感谢@Nkosi 的帮助,它帮助我找到解决方案:)。 我也受到了其他网站的启发:

我也更新了我的回购解决方案

以下是重要部分:

测试服务器夹具:

public class TestServerFixture : WebApplicationFactory<TestStartup>
{
    public HttpClient Client { get; }
    public ITestOutputHelper Output { get; set; }

    protected override IHostBuilder CreateHostBuilder()
    {
        var builder = Host.CreateDefaultBuilder()
            .ConfigureLogging(logging =>
            {
                logging.ClearProviders(); //All API logging providers are cleared
                logging.AddXunit(Output); //Internal extension which redirect all log to the ITestOutputHelper 
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder
                    .UseStartup<TestStartup>()
                    .ConfigureTestServices((services) =>
                    {
                        //Without that, the client always returns 404
                        //(even if it has already been set in Startup.Configure)
                        services
                            .AddControllers()
                            .AddApplicationPart(typeof(Startup).Assembly);
                    });
            });

        return builder;
    }

    //ITestOutputHelper is set in the constructor of the Test class
    public TestServerFixture SetOutPut(ITestOutputHelper output)
    {
        Output = output;
        return this;
    }

    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);
        Output = null;
    }
}

WeatherForecastController_Tests:

public class WeatherForecastController_Tests : IClassFixture<TestServerFixture>
{
    public TestServerFixture TestServerFixture { get; private set; }
    public HttpClient Client { get; private set; }
    public ITestOutputHelper Output { get { return TestServerFixture.Output; } }

    public WeatherForecastController_Tests(TestServerFixture testServerFixture, ITestOutputHelper output)
    {
        TestServerFixture = testServerFixture.SetOutPut(output);
        Client = testServerFixture.CreateClient();
    }

    [...]
}

如果您有任何改进代码的建议或问题,请告诉我:)

我查看了您的代码,经过一些研究,我得出的结论是,通过构造函数注入将ITestOutputHelper注入TestServerFixture是不可行的。 我也研究了财产注入,但我相信它可能最终会在财产被填充之前被使用。

这里的主要问题是创建WebApplicationFactory时如何调用事物的流程。

通过在构造函数中创建Client ,它会触发一系列事件,阻止您使用ITestOutputHelper

我建议推迟Client的创建,以便可以在之前设置依赖项。

public class TestServerFixture : WebApplicationFactory<TestStartup> {
    private Lazy<HttpClient> client = new Lazy<HttpClient>(() => return Server.CreateClient());

    private IHost _host;
    public HttpClient Client => client.Value;
    public ITestOutputHelper Output { get; set; }

    public TestServerFixture(){
        //...
    }

    //...all other code remains the same
}

注意Lazy<HttpClient> 这是为了推迟客户端的创建,以便可以首先填充ITestOutputHelper

public class WeatherForecastController_Tests : IClassFixture<TestServerFixture> {
    public WeatherForecastController_Tests(TestServerFixture testServerFixture, ITestOutputHelper output) {
        Output = output;
        testServerFixture.Output = Output;
        Client = testServerFixture.Client;            
    }

    //...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM