我针对集成测试升级到.net core 3.0时遇到的问题进行了回购: https://github.com/ranouf/TestingWithDotNetCore3_0
启动测试时,出现以下问题: 讯息:
System.AggregateException:发生一个或多个错误。 (类夹具类型“ MyIntegrationTests.TestServerFixture”具有一个或多个 尚未解决的构造函数参数:ITestOutputHelper输出)( 以下构造函数参数没有匹配的灯具数据: TestServerFixture testServerFixture) ----类夹具类型“ MyIntegrationTests.TestServerFixture”具有一个或多个未解析的构造函数参数:ITestOutputHelper输出 ----以下构造函数参数没有匹配的夹具数据:TestServerFixture testServerFixture堆栈跟踪: -----内部堆栈跟踪#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;
}
TestStartup:
public class TestStartup : Startup
{
public TestStartup(IConfiguration configuration)
: base(configuration)
{
}
public override void SetUpDataBase(IServiceCollection services)
{
// here is where I use the InMemoryDatabase
}
}
TestServerFixture:
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的Iod testServerFixture和ITestOutputHelper输出不起作用。如何运作?
答案 0 :(得分:1)
我检查了您的代码,经过研究后得出的结论是,通过构造函数注入将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;
}
//...
答案 1 :(得分:0)
感谢@Nkosi的帮助,它帮助我找到了解决方案:)。 我也受到其他网站的启发:
我也在仓库上更新了解决方案
以下是重要部分:
TestServerFixture:
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();
}
[...]
}
如果您有任何改进代码或问题的建议,请告诉我:)