Net Core 集成测试:运行 Startup.cs 和来自其他程序的配置
Net Core Integration Test: Run Startup.cs and Configuration from other Program
我们正在创建一个集成单元测试 (Xunit),它正在调用真实应用程序 Startup.cs。
出于某种原因,真实项目可以正确读取配置 file/property,但是 运行 它无法从集成测试中读取。它没有将任何内容放入下面的 Configuration (conf) 变量中。我将如何解决这个问题?
原因是它没有接受是因为它没有读取 Net Core 2.2 中新的内部依赖注入,它读取配置文件。现在正在尝试使用 .CreateDefaultBuilder。
IntegrationTest1.cs
TestServer _server = new TestServer(new WebHostBuilder() .UseContentRoot("C:\RealProject\RealProject.WebAPI")
.UseEnvironment("Development")
.UseConfiguration(new ConfigurationBuilder()
.SetBasePath("C:\RealProject\RealProject.WebAPI")
.AddJsonFile("appsettings.json")
.Build())
.UseStartup<Startup>()
.UseStartup<Startup>());
真实项目Startup.cs
public Startup(IConfiguration configuration, IHostingEnvironment hostingEnvironment)
{
Configuration = configuration;
HostingEnvironment = hostingEnvironment;
}
public IHostingEnvironment HostingEnvironment { get; }
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public IServiceProvider ConfigureServices(IServiceCollection services)
{
var conf = Configuration;
IConfiguration appConf = conf.GetSection("ConnectionStrings");
var connstring = appConf.GetValue<string>("DatabaseConnection");
services.AddDbContext<DbContext>(a => a.UseSqlServer(connstring));
Appsettings.Json
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"ConnectionStrings": {
"DatabaseConnection": "Data Source=.;Initial Catalog=ApplicationDatabase;Integrated Security=True"
}
}
您要做的是为您的 WebApplication 创建一个采用 Startup 类型的工厂。然后,您可以使用 IClassFixture
接口与测试 class.
中的所有测试共享此工厂的上下文
实际情况是这样的:
public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<Startup> where TStartup : class
{
public CustomWebApplicationFactory() { }
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder
.ConfigureTestServices(
services =>
{
services.Configure(AzureADDefaults.OpenIdScheme, (System.Action<OpenIdConnectOptions>)(o =>
{
// CookieContainer doesn't allow cookies from other paths
o.CorrelationCookie.Path = "/";
o.NonceCookie.Path = "/";
}));
}
)
.UseEnvironment("Production")
.UseStartup<Startup>();
}
}
public class AuthenticationTests : IClassFixture<CustomWebApplicationFactory<Startup>>
{
private HttpClient _httpClient { get; }
public AuthenticationTests(CustomWebApplicationFactory<Startup> fixture)
{
WebApplicationFactoryClientOptions webAppFactoryClientOptions = new WebApplicationFactoryClientOptions
{
// Disallow redirect so that we can check the following: Status code is redirect and redirect url is login url
// As per https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-2.2#test-a-secure-endpoint
AllowAutoRedirect = false
};
_httpClient = fixture.CreateClient(webAppFactoryClientOptions);
}
[Theory]
[InlineData("/")]
[InlineData("/Index")]
[InlineData("/Error")]
public async Task Get_PagesNotRequiringAuthenticationWithoutAuthentication_ReturnsSuccessCode(string url)
{
// Act
HttpResponseMessage response = await _httpClient.GetAsync(url);
// Assert
response.EnsureSuccessStatusCode();
}
}
我按照指南 here 在我自己的代码中实现了这一点。
我们正在创建一个集成单元测试 (Xunit),它正在调用真实应用程序 Startup.cs。
出于某种原因,真实项目可以正确读取配置 file/property,但是 运行 它无法从集成测试中读取。它没有将任何内容放入下面的 Configuration (conf) 变量中。我将如何解决这个问题? 原因是它没有接受是因为它没有读取 Net Core 2.2 中新的内部依赖注入,它读取配置文件。现在正在尝试使用 .CreateDefaultBuilder。
IntegrationTest1.cs
TestServer _server = new TestServer(new WebHostBuilder() .UseContentRoot("C:\RealProject\RealProject.WebAPI")
.UseEnvironment("Development")
.UseConfiguration(new ConfigurationBuilder()
.SetBasePath("C:\RealProject\RealProject.WebAPI")
.AddJsonFile("appsettings.json")
.Build())
.UseStartup<Startup>()
.UseStartup<Startup>());
真实项目Startup.cs
public Startup(IConfiguration configuration, IHostingEnvironment hostingEnvironment)
{
Configuration = configuration;
HostingEnvironment = hostingEnvironment;
}
public IHostingEnvironment HostingEnvironment { get; }
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public IServiceProvider ConfigureServices(IServiceCollection services)
{
var conf = Configuration;
IConfiguration appConf = conf.GetSection("ConnectionStrings");
var connstring = appConf.GetValue<string>("DatabaseConnection");
services.AddDbContext<DbContext>(a => a.UseSqlServer(connstring));
Appsettings.Json
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"ConnectionStrings": {
"DatabaseConnection": "Data Source=.;Initial Catalog=ApplicationDatabase;Integrated Security=True"
}
}
您要做的是为您的 WebApplication 创建一个采用 Startup 类型的工厂。然后,您可以使用 IClassFixture
接口与测试 class.
实际情况是这样的:
public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<Startup> where TStartup : class
{
public CustomWebApplicationFactory() { }
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder
.ConfigureTestServices(
services =>
{
services.Configure(AzureADDefaults.OpenIdScheme, (System.Action<OpenIdConnectOptions>)(o =>
{
// CookieContainer doesn't allow cookies from other paths
o.CorrelationCookie.Path = "/";
o.NonceCookie.Path = "/";
}));
}
)
.UseEnvironment("Production")
.UseStartup<Startup>();
}
}
public class AuthenticationTests : IClassFixture<CustomWebApplicationFactory<Startup>>
{
private HttpClient _httpClient { get; }
public AuthenticationTests(CustomWebApplicationFactory<Startup> fixture)
{
WebApplicationFactoryClientOptions webAppFactoryClientOptions = new WebApplicationFactoryClientOptions
{
// Disallow redirect so that we can check the following: Status code is redirect and redirect url is login url
// As per https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-2.2#test-a-secure-endpoint
AllowAutoRedirect = false
};
_httpClient = fixture.CreateClient(webAppFactoryClientOptions);
}
[Theory]
[InlineData("/")]
[InlineData("/Index")]
[InlineData("/Error")]
public async Task Get_PagesNotRequiringAuthenticationWithoutAuthentication_ReturnsSuccessCode(string url)
{
// Act
HttpResponseMessage response = await _httpClient.GetAsync(url);
// Assert
response.EnsureSuccessStatusCode();
}
}
我按照指南 here 在我自己的代码中实现了这一点。