c# - .net 核心集成测试:API 控制器操作未从测试中调用。如何在测试项目中模拟 opeind 连接身份验证?
问题描述
启动 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" });
});
}
}
控制器装饰为:
[Route("api/[controller]")]
public class SearchController : BaseController
控制器动作被装饰为:
[Route("TestMethod")]
[ActionName("TestMethod")]
[HttpGet]
public async Task<EmptyResult> Test()
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/");
}
测试为事实:
[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 并且 SearchController 操作未被调用。使用启动配置文件解决所有依赖项
任何想法 ???
解决方案
您可以检查内容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
,您将需要模拟登录过程,这是 Identity 的链接,您可以尝试为 AAD 实现自己的登录。
推荐阅读
- javascript - 如何设置滚动视频的长度以始终匹配页面的高度?(可以随窗口大小和不同设备而变化)
- crystal-reports - 如何在 Crystal 报表中使用 Google Charts 显示 QR 码?
- google-sheets - 如何创建返回 TRUE 和 FALSE 数组而不是单数 TRUE 或 FALSE 的 Google 表格和公式?
- javascript - 如何使用 jQuery 将 HTML 导出为 PDF(多页)?
- python - 启动器中的致命错误:使用烧瓶运行时
- odoo - 如何更改/更新自定义主题预览图像(缩略图)
- c++ - 创建一个抽象类,从中派生bass类c ++
- angular - Angular 和 NGX-Masonry - 显示问题
- puppeteer - 用 Puppeteer 中的锚链接刮掉 html 中的段落
- linux - 如何在 Linux 内核模块中找到合适的 DWARF 符号作为地址?