c# - 如何在集成测试中从服务中删除 AuthorizeAreaFolder 选项
问题描述
我使用自定义 WebApplicationFactory 对我的 razor Web 应用程序进行了集成测试:
public class CustomWebApplicationFactory<TStartup>
: WebApplicationFactory<TStartup> where TStartup : class
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureServices(services =>
{
var descriptor = services.SingleOrDefault(
d => d.ServiceType ==
typeof(DbContextOptions<GenericDbContext>));
services.Remove(descriptor);
services.AddDbContext<GenericDbContext>(options =>
{
options.UseInMemoryDatabase("InMemoryDbForTesting");
});
var sp = services.BuildServiceProvider();
using var scope = sp.CreateScope();
var scopedServices = scope.ServiceProvider;
var db = scopedServices.GetRequiredService<GenericDbContext>();
var logger = scopedServices
.GetRequiredService<ILogger<CustomWebApplicationFactory<TStartup>>>();
db.Database.EnsureCreated();
try
{
Utilities.InitializeDbForTests(db);
}
catch (Exception ex)
{
logger.LogError(ex, "An error occurred seeding the " +
"database with test messages. Error: {Message}", ex.Message);
}
});
}
}
在 TStartup 我通过这个启动配置服务:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
//AzureADB2C
services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddAzureAdB2C(options => Configuration.Bind("Authentication:AzureAdB2C", options))
.AddCookie(options =>
{
options.Cookie.SameSite = SameSiteMode.None;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.IsEssential = true;
//options.ExpireTimeSpan = TimeSpan.FromDays(365);
});
//AzureADB2C
//Simple
//services.AddAuthentication(AzureADB2CDefaults.AuthenticationScheme)
// .AddAzureADB2C(options => Configuration.Bind("Authentication:AzureAdB2C", options));
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => false; // = context => true; //When set to true, TempData will not work unless the user opts in.
options.MinimumSameSitePolicy = SameSiteMode.Unspecified; //If we dont do the hack for chrome/safari, this should be set to 'None'
options.Secure = CookieSecurePolicy.Always;
//Hack for Chrome/Safari. May not be needed in future
options.OnAppendCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
options.OnDeleteCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
});
services.AddRouting(options => {
options.LowercaseUrls = true;
//options.AppendTrailingSlash = false;
});
//Response Caching
services.AddResponseCaching();
//With conditional runtime compilation
IMvcBuilder builder = services.AddRazorPages()
.AddRazorPagesOptions(options =>
{
//Sitemap
options.Conventions.AddAreaPageRoute("xxxxxx", "/xxxxxx", "xxxxxx.xml");
options.Conventions.AddAreaPageRoute("xxxxxx", "/xxxxxx", "xxxxxx/xxxxxx.xml");
options.Conventions.AddAreaPageRoute("xxxxxx", "/xxxxxx", "xxxxxx/xxxxxx.xml");
options.Conventions.AddAreaPageRoute("xxxxxx", "/xxxxxx", "xxxxxx/xxxxxx.xml");
options.Conventions.AddAreaPageRoute("xxxxxx", "/xxxxxx", "xxxxxx/xxxxxx.xml");
options.Conventions.AddAreaPageRoute("xxxxxx", "/xxxxxx", "xxxxxx/xxxxxx.xml");
options.Conventions.AddAreaPageRoute("xxxxxx", "/xxxxxx", "xxxxxx/xxxxxx.xml");
options.Conventions.AuthorizeAreaFolder("xxxxxx", "/");
options.Conventions.AuthorizeAreaFolder("xxxxxx", "/");
options.Conventions.AuthorizeAreaFolder("xxxxxxx", "/", "xxxxx");
//options.Conventions.AuthorizeAreaFolder("xxxx", "/");
options.Conventions.AuthorizeAreaFolder("xxxxxx", "/");
options.Conventions.AuthorizeAreaFolder("xxxxxx", "/");
options.Conventions.AuthorizeAreaFolder("xxxxxx", "/");
//options.Conventions.AuthorizeAreaFolder("xxxxx", "/");
options.Conventions.AuthorizeAreaPage("xxxx", "/xxxxx");
//password reset
options.Conventions.AllowAnonymousToAreaPage("xxxxx", "/xxxxx");
options.Conventions.AllowAnonymousToAreaPage("xxxxx", "/xxxx");
//Checkout and 3DS pages
options.Conventions.AllowAnonymousToAreaPage("xxxxx", "/xxxxx");
});
services.AddMemoryCache();
//CACHE for tokens
// Adds a default in-memory implementation of IDistributedCache.
services.AddDistributedMemoryCache();
//services.AddSession();
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromHours(1);
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.SameSite = SameSiteMode.Unspecified;// SameSiteMode.None;
//options.IdleTimeout = TimeSpan.FromDays(365);
});
services.AddDbContext<IGenericDbContext, GenericDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("GenericDbConnection")));
}
就像我在自定义 WebApplicationFactory 中删除 dbContextOption 一样,我想删除 AuthorizeAreaFolder 或覆盖“services.AddRazorPages().AddRazorPagesOptions()”以允许集成测试在不伪造授权的情况下获取或发布页面。
解决方案
AddRazorPagesOptions
本质上只是RazorPagesOptions
在服务集合上配置了,所以相当于如下:
services.Configure<RazorPagesOptions>(options =>
{
options.Conventions.AuthorizeAreaFolder("xxxxxx", "/");
// …
});
这也意味着为了更改约定,您可以RazorPagesOptions
直接重新配置和修改约定集合。不幸的是,这些IPageConvention
类型是私有的,因此您无法查找AuthorizeAreaFolder
直接添加的条目并使用该RemoveType
方法将其删除。但是,您可以清除整个集合以完全删除所有约定:
services.Configure<RazorPagesOptions>(options =>
{
options.Conventions.Clear();
});
推荐阅读
- collapse - 在引导程序中折叠
- javascript - 当输入无效时,角度反应形式+材料输入在第一个焦点上不显示红色边框
- apache-spark - 带有检查点的 Pyspark Streaming 失败
- laravel - Laravel:尝试访问 null 类型值的数组偏移量
- java - 尝试购买订阅时未启动订阅付款窗口
- mobile - 视口问题
- python-3.x - 避免 Python 多处理中的竞争条件
- python - ModuleNotFoundError:虚拟环境中没有名为“pip”的模块
- python - 如何将 jupyter 实验室笔记本作为 .bat 脚本运行(使用 Anaconda 环境)
- swift - Swift:从自定义实现调用协议函数的默认实现