简体   繁体   English

.net 核心集成测试:API 控制器操作未从测试中调用。 如何在测试项目中模拟开放连接身份验证?

[英].net Core Integration Test : API Controller Action Not getting called from Test. How to mock opeind connect authentication in test project?

start up cs file .net core: (This is also get called while creating test server)启动 cs 文件 .net core : (这也在创建测试服务器时被调用)

 public class Startup
{
    private IHostingEnvironment env;
    private Dictionary<string, string> secretlist = new Dictionary<string, string>();

    public Startup(IConfiguration configuration, IHostingEnvironment env)
    {         
        this.Configuration = configuration;
        this.CurrentEnvironment = env;

    }

    public Startup(IHostingEnvironment env)
    {
        this.env = env;
    }

    public IConfiguration Configuration { get; }

    private IHostingEnvironment CurrentEnvironment { get; set; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<FormOptions>(x =>
        {
            x.ValueLengthLimit = int.MaxValue;
            x.MultipartBodyLengthLimit = int.MaxValue;
            x.MultipartHeadersLengthLimit = int.MaxValue;
        });

        services.AddApplicationInsightsTelemetry(this.Configuration);
        services.AddSingleton<ITelemetryInitializer, AppInsightsInitializer>();

        // Adds services required for using options.
        services.AddOptions();

        services.Configure<AppSettingsConfig>(this.Configuration.GetSection("AppSettings"));

        if (this.CurrentEnvironment.IsDevelopment())
        {
            services.AddDataProtection()
               .PersistKeysToFileSystem(new DirectoryInfo(Environment.ExpandEnvironmentVariables(this.Configuration.GetValue<string>("AppSettings:KeyStorage_UNCPath"))))
               .ProtectKeysWithDpapiNG();
        }
        else
        {
            CloudStorageAccount storageAccount = new CloudStorageAccount(
                new Microsoft.WindowsAzure.Storage.Auth.StorageCredentials(
                                                 this.Configuration.GetValue<string>("AppSettings:StorageAccountName"),
                                                this.Configuration.GetValue<string>("AppSettings:StorageAccessValue")), true);

            //Create blob client
            CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
            // Get a reference to a container named "keycontainer."
            CloudBlobContainer container = blobClient.GetContainerReference("keycontainer");
            services.AddDataProtection().PersistKeysToAzureBlobStorage(container, "keys.xml");
        }

        services.Configure<AppSettingsConfig>(options =>
        {
            if (!this.CurrentEnvironment.IsDevelopment())
            {

            }
        });

        var azureAdConfig = new AzureAdConfig();
        this.Configuration.GetSection("Authentication:AzureAd").Bind(azureAdConfig);
        services.Configure<AzureAdConfig>(this.Configuration.GetSection("Authentication:AzureAd"));

        var connectionStringsConfig = new ConnectionStringsConfig();
        connectionStringsConfig.oneConnection = this.secretlist["ConnectionStrings"];
        //this.Configuration.GetSection("ConnectionStrings").Bind(connectionStringsConfig);
        //services.Configure<ConnectionStringsConfig>(this.Configuration.GetSection("ConnectionStrings"));



        if (this.RequireAAD())
        {
            // Add framework services.
            services.Configure<MvcOptions>(options =>
            {
                options.Filters.Add(new RequireHttpsAttribute());
            });
        }
        else
        {
            services.Configure<MvcOptions>(options =>
            {
            });
        }

        // Add Authentication services.
        if (this.RequireAAD())
        {
            // Configure the OWIN pipeline to use cookie auth.
            services.AddAuthentication(options =>
            {
                options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
            })
            .AddCookie()
            // Configure the OWIN pipeline to use OpenID Connect auth.
            // https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-openid-connect-code
            .AddOpenIdConnect(options =>
            {
                options.ClientId = azureAdConfig.ClientId;
                options.ClientSecret = azureAdConfig.ClientSecret;
                options.Authority = string.Format(azureAdConfig.AADInstance, azureAdConfig.Tenant);
                options.ResponseType = OpenIdConnectResponseType.CodeIdToken;
                options.Resource = azureAdConfig.ResourceURI_Graph;
                // PostLogoutRedirectUri = Configuration["AzureAd:PostLogoutRedirectUri"],
                options.Events = new AuthEvents(azureAdConfig, connectionStringsConfig);
            });




        if (this.RequireAAD())
        {
            services.AddMvc(config =>
            {
                var policy = new AuthorizationPolicyBuilder()
                                 .RequireAuthenticatedUser()
                                 .Build();
                config.Filters.Add(new Microsoft​.AspNetCore​.Mvc​.Authorization.AuthorizeFilter(policy));
                config.Filters.Add(typeof(ExceptionFilter));
            });
        }
        else
        {
            services.AddMvc();
        }
        if (this.Configuration.GetValue<bool>("API: SWITCH_ENABLE_API", true))
        {
            //services.AddScoped<IDBOperation, Operations>();
            services.AddScoped<ILookupSearch, Operations>();
            services.AddScoped<IFullSearch, Operations>();
        }

        services.AddSingleton<Common.Data.RepositoryFactories>(new Common.Data.RepositoryFactories(new Dictionary<Type, Func<DbContext, object>>
            {
                { typeof(IQueryRepository), dbcontext => new QueryRepository(dbcontext) },
                { typeof(IDomainValuesRepository), dbcontext => new DomainValuesRepository(dbcontext) },
                { typeof(IRequestsRepository), dbcontext => new RequestsRepository(dbcontext) },

                // { typeof(IoneDomainValuesRepository), dbcontext => new oneDomainValuesRepository(dbcontext) }
        }));

        services.AddTransient<Common.Contracts.IRepositoryProvider, Common.Data.RepositoryProvider>();
        services.AddScoped<one.Data.Contracts.IoneUow, one.Data.oneUow>();
        services.AddTransient<IUow,Uow>();
        // For accessing appinsights for dependency injection?
        services.AddApplicationInsightsTelemetry();

        // For Storing Tokens in DB
        services.AddDistributedSqlServerCache(o =>
        {
            o.ConnectionString = this.secretlist["ConnectionStrings"];
           // o.ConnectionString = this.Configuration.GetConnectionString("oneConnection");
            // o.ConnectionString = this.Configuration[this.Configuration.GetSection("KeyVaultSeetings")["oneConnectionString"]];
            o.SchemaName = "dbo";
            o.TableName = "CacheTable";
        });
        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        services.AddSingleton<IEntityExtractor, EntityExtractor>();
        services.AddScoped<ITokenCacheService, DistributedTokenCacheService>();
        services.AddScoped<ITokenService, TokenService>();
        services.AddTransient<IAPIClient,APIClient>();
    }

    /// <summary>
    ///  This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    /// </summary>
    /// <param name="app"></param>
    /// <param name="env"></param>
    /// <param name="loggerFactory"></param>
    /// <param name="tc"></param>
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, TelemetryClient tc)
    {
        var azureAdConfig = new AzureAdConfig();
        this.Configuration.GetSection("Authentication:AzureAd").Bind(azureAdConfig);
        loggerFactory.AddConsole(this.Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();
        loggerFactory.AddProvider(new MyFilteredLoggerProvider(tc));
        loggerFactory.AddApplicationInsights(app.ApplicationServices, this.Configuration.GetValue<string>("Logging:LogLevel:Default") == "Information" ? Microsoft.Extensions.Logging.LogLevel.Information : Microsoft.Extensions.Logging.LogLevel.Warning);

        this.SetupStore(app);

        app.UseRewriter(new RewriteOptions().AddRedirectToHttps());

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
            {
                HotModuleReplacement = true
            });
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }

        // TODO . Switch
        app.UseStaticFiles();

        if (this.RequireAAD())
        {
            app.UseAuthentication();
        }

        app.UseMiddleware(typeof(ErrorHandlingMiddleware));
        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");

            routes.MapSpaFallbackRoute(
                name: "spa-fallback",
                defaults: new { controller = "Home", action = "Index" });
        });
    }

} }

Controller is decorated as :控制器装饰为:

 [Route("api/[controller]")]
    public class SearchController : BaseController

Controller Action is decorated as :控制器动作被修饰为:

[Route("TestMethod")]
        [ActionName("TestMethod")]
        [HttpGet]
        public async Task<EmptyResult> Test()

Configuration of TestServer Test CS file : TestServer 测试 CS 文件的配置:

    public DemoTest()
     {
        // Set up server configuration
        var configuration = new ConfigurationBuilder()                                                              
                            .AddJsonFile(@"appsettings.json")
                            .Build();
        // Create builder
        var builder = new WebHostBuilder()                                                     
                        .UseStartup<Startup>()
                        .UseConfiguration(configuration);
        // Create test server
        var server = new TestServer(builder);
        // Create database context
        this._context = server.Host.Services.GetService(typeof(DBContext)) as DBContext;

        // Create client to query server endpoints
        this._client = server.CreateClient();
        _client.BaseAddress = new Uri("https://localhost:44316/");
}

Test as a Fact :事实测试:

  [Fact]
    public async Task Test()
    {
        try
        {

            var response = await this._client.GetAsync("/api/Search/TestMethod");
            response.EnsureSuccessStatusCode();
            var responseString = await response.Content.ReadAsStringAsync();
            //Assert.False(result != null);
        }
        catch (Exception ex)
        {
            throw;
        }

    }

Getting Status as 302 and SearchController action is not getting called.获取状态为 302 并且未调用 SearchController 操作。 All the dependencies are resolved using start up configuration file使用启动配置文件解决所有依赖项

Any idea ???任何的想法 ???

You could check the content for var responseString = await response.Content.ReadAsStringAsync();您可以检查var responseString = await response.Content.ReadAsStringAsync();的内容var responseString = await response.Content.ReadAsStringAsync(); to see what the content is.看看内容是什么。

I assume it is the login page which is due to that you required Authorize .我认为这是由于您需要Authorize的登录页面。

First, try to remove the code below for a try.首先,尝试删除下面的代码进行尝试。

services.AddMvc(config =>
        {
            //var policy = new AuthorizationPolicyBuilder()
                             .RequireAuthenticatedUser()
                             .Build();
            //config.Filters.Add(new Microsoft​.AspNetCore​.Mvc​.Authorization.AuthorizeFilter(policy));
            config.Filters.Add(typeof(ExceptionFilter));
        });

For Authentication , you will need to imitate the login process, here is a link for Identity, you could try implement your own login for AAD.对于Authentication ,您需要模拟登录过程,这里是 Identity 的链接,您可以尝试实现自己的 AAD 登录。

Razor Pages .NET Core 2.1 Integration Testing post authentication Razor Pages .NET Core 2.1 集成测试后身份验证

暂无
暂无

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

相关问题 如何在 ASP.NET Core 中为单元/集成测试模拟 IFormFile? - How to mock an IFormFile for a unit/integration test in ASP.NET Core? 在 xUnit 测试项目 (.NET Core) 中完成集成测试后如何关闭 Resharper 测试运行器? - How to close Resharper test runner after finishing integration test in xUnit Test project (.NET Core)? 如何在.NET Core中测试控制器 - How to test a controller in .NET Core 单元测试 .NET 核心 3 Web API Controller - Unit test .NET Core 3 Web API Controller 单元测试。 如何在测试中打开表格? - UNIT test. How to open the form in the test? 使用ASP.NET Core 2.0集成测试HttpClient如何通过依赖项注入模拟DateTime.Now - Integration test HttpClient using ASP.NET Core 2.0 How to mock DateTime.Now with dependency injection 从 .net 核心集成测试项目加载引用的程序集不包括来自测试的 API 的引用项目 - Load referenced assemblies from a .net core Integration Test project doesn't include referenced projects from tested API 使用asp.net核心中的Identity server4进行登录控制器的API集成测试 - API Integration Test for Login controller using Identity server4 in asp.net core 如何集成测试依赖于独立Asp.Net Core Api的Asp.Net Core客户端应用程序 - How to integration test an Asp.Net Core client app that relies on independent Asp.Net Core Api 将测试项目 appSettings 附加到 ASP.NET Core 集成测试 - Append test project appSettings to ASP.NET Core integration tests
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM