Identityserver4 与内存中IdentityServer的集成测试

Identityserver4 与内存中IdentityServer的集成测试,identityserver4,Identityserver4,我有一个API,它使用IdentityServer4进行令牌验证。 我想用内存中的TestServer对这个API进行单元测试。我想在内存测试服务器中托管IdentityServer 我已设法从IdentityServer创建了一个令牌 这是我已经走了多远,但我得到一个错误“无法从中获取配置”http://localhost:54100/.well-已知/openid配置” Api使用具有不同策略的[Authorize]-属性。这就是我想要测试的 这能做到吗?我做错了什么? 我曾尝试查看Iden

我有一个API,它使用IdentityServer4进行令牌验证。 我想用内存中的TestServer对这个API进行单元测试。我想在内存测试服务器中托管IdentityServer

我已设法从IdentityServer创建了一个令牌

这是我已经走了多远,但我得到一个错误“无法从中获取配置”http://localhost:54100/.well-已知/openid配置”

Api使用具有不同策略的[Authorize]-属性。这就是我想要测试的

这能做到吗?我做错了什么? 我曾尝试查看IdentityServer4的源代码,但没有遇到类似的集成测试场景

protectedintegrationtestbase()
{
var startupAssembly=typeof(Startup).GetTypeInfo().Assembly;
_contentRoot=SolutionPathUtility.GetProjectPath(@“”,startupAssembly);
配置(_contentRoot);
var orderApiServerBuilder=new WebHostBuilder()
.UseContentRoot(\u contentRoot)
.ConfigureServices(初始化服务)
.UseStartup();
orderApiServerBuilder.Configure(ConfigureApp);
OrderApiTestServer=newtestserver(orderApiServerBuilder);
HttpClient=OrderApiTestServer.CreateClient();
}
私有void初始化服务(IServiceCollection服务)
{
var cert=new X509Certificate2(Path.Combine(_contentRoot,“idsvr3test.pfx”),“idsrv3test”);
services.AddIdentityServer(选项=>
{
options.IssuerUri=”http://localhost:54100";
})
.AddInMemoryClients(Clients.Get())
.AddInMemoryScopes(Scopes.Get())
.AddInMemoryUsers(Users.Get())
.SetSigningCredential(证书);
services.AddAuthorization(选项=>
{
options.AddPolicy(OrderApiConstants.StoreIdPolicyName,policy=>policy.Requirements.Add(newstoreidrequirement(“storeId”));
});
services.AddSingleton();
services.AddSingleton(_orderManagerMock.Object);
services.AddMvc();
}
专用void配置应用程序(IApplicationBuilder应用程序)
{
app.UseIdentityServer();
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
var options=new IdentityServerAuthenticationOptions
{
Authority=\u appsettings.IdentityServerAddress,
RequireHttpsMetadata=false,
ScopeName=\u appsettings.IdentityServerScopeName,
自动验证=错误
};
app.useIdentityServer身份验证(选项);
app.UseMvc();
}
在我的单元测试中:

私有HttpMessageHandler\u处理程序;
常量字符串标记端点=”http://localhost/connect/token";
公开考试()
{
_handler=OrderApiTestServer.CreateHandler();
}
[事实]
公共异步任务LeTest()
{
var accessToken=await GetToken();
HttpClient.SetBearerToken(accessToken);
var httpResponseMessage=await HttpClient.GetAsync(“stores/11/orders/asdf”);//此行失败
}
私有异步任务GetToken()
{
var client=new-TokenClient(TokenEndpoint,“client”,“secret”,innerHttpMessageHandler:_handler);
var response=wait client.RequestClientCredentialsAsync(“TheMOON.OrderApi”);
返回response.AccessToken;
}

我认为您可能需要对授权中间件进行双重测试,这取决于您需要多少功能。因此,基本上您需要一个中间件,它完成授权中间件所做的一切,减去对发现文档的反向通道调用

IdentityServer4.AccessTokenValidation是两个中间件的包装器。
JwtBearerAuthentication
中间件和
oauth2introsectionauthentication
中间件。这两种方法都通过http获取用于令牌验证的发现文档。如果要进行内存中的自包含测试,这是一个问题

如果要解决此问题,可能需要制作一个假的
app.UseIdentityServerAuthentication
版本,该版本不执行获取发现文档的外部调用。它只填充HttpContext主体,以便测试您的[Authorize]策略


查看IdentityServer4.AccessTokenValidation的具体内容。接下来看看JWT中间件的外观

我知道需要一个比@james fera发布的更完整的答案。我从他的回答中学到了一些东西,并做了一个github项目,包括一个测试项目和一个API项目。代码应该是自解释的,不难理解

IdentityServerSetup.cs
类可以被抽象掉,例如NuGetted,留下基类
IntegrationTestBase.cs

其本质是,可以使测试IdentityServer像普通IdentityServer一样工作,具有用户、客户端、作用域、密码等。我使用DELETE方法[Authorize(Role=“admin)]来证明这一点

我建议不要在这里发布代码,而是阅读@james fera的帖子,了解基本知识,然后启动我的项目并运行测试


IdentityServer是一个非常好的工具,并且能够使用TestServer框架,它变得更好。

您在最初的问题中发布的代码是正确的

IdentityServerAuthenticationOptions对象的属性可覆盖用于反向通道通信的默认HttpMessageHandlers

将其与TestServer对象上的CreateHandler()方法相结合后,您将得到:

//在此处构建identity server
var idBuilder=new WebBuilderHost();
idBuilder.UseStartup();
//...
TestServer identityTestServer=新的TestServer(idBuilder);
var identityServerClient=identityTestServer.CreateClient();
var token=//使用IdentityServer客户端从IdentityServer获取令牌
//构建Api测试服务器
var options=new IdentityServerAuthenticationOptions()
{
权威=”http://localhost:5001",
//重要部分H