首页 > 解决方案 > 如何在集成测试中从服务中删除 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()”以允许集成测试在不伪造授权的情况下获取或发布页面。

标签: c#integration-testingrazor-pagesasp.net-core-3.1xunit.net

解决方案


AddRazorPagesOptions本质上只是RazorPagesOptions在服务集合上配置了,所以相当于如下:

services.Configure<RazorPagesOptions>(options =>
{
    options.Conventions.AuthorizeAreaFolder("xxxxxx", "/");
    // …
});

这也意味着为了更改约定,您可以RazorPagesOptions直接重新配置和修改约定集合。不幸的是,这些IPageConvention类型是私有的,因此您无法查找AuthorizeAreaFolder直接添加的条目并使用该RemoveType方法将其删除。但是,您可以清除整个集合以完全删除所有约定:

services.Configure<RazorPagesOptions>(options =>
{
    options.Conventions.Clear();
});

推荐阅读