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



启动 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://learn.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" });
});
}

}

控制器装饰为:

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

控制器操作修饰为:

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

测试服务器测试 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/");
}

测试作为事实:

[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;
}
}

获取状态为 302 并且搜索控制器操作未获得 叫。所有依赖项都使用启动配置解析 文件

任何想法???

您可以检查var responseString = await response.Content.ReadAsStringAsync();的内容以查看内容是什么。

我假设这是登录页面,这是由于您需要Authorize

首先,尝试删除下面的代码进行尝试。

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

对于Authentication,你将需要模仿登录过程,这里是标识的链接,你可以尝试实现自己的 AAD 登录。

Razor 页面 .NET Core 2.1 集成 身份验证后测试

最新更新