ClaimsIdentity 用户在测试期间未被识别为已登录
ClaimsIdentity user is not recognized as logged in during test
我正在尝试在我正在处理的新项目中建立单元测试。我正在使用 ASP.NET Boilerplate(.NET Core,多页面应用程序)和预构建的身份验证作为我的起点。自 , I am attempting to create my own, pulling from what was provided in the ASP.NET Core template。我已经能够建立一个使用 InMemoryDatabase
进行测试的 Startup
class。但是,最基本的测试没有通过。我一直坚持拥有一个经过完全身份验证并被识别为 'logged in' 的测试用户。被测代码是这样的:
[AbpMvcAuthorize]
public class HomeController : ProjectControllerBase
{
public ActionResult Index()
{
return View();
}
}
测试是这样写的:
[Fact]
public async Task Index_Test()
{
// Added as part of suggestions made by 'https://medium.com/@zbartl/authentication-and-asp-net-core-integration-testing-using-testserver-15d47b03045a'
Client.DefaultRequestHeaders.Add("my-name", "admin");
Client.DefaultRequestHeaders.Add("my-id", "2");
// Act
var response = await GetResponseAsStringAsync(
GetUrl<HomeController>(nameof(HomeController.Index))
);
// Assert
response.ShouldNotBeNullOrEmpty();
}
引用 here 的博客允许我使用 Middleware
class 提供 ClaimsPrincipal
和 ClaimsIdentity
。中间件 class 看起来像这样:
public class TestAuthenticationMiddleware
{
private readonly RequestDelegate _next;
public TestAuthenticationMiddleware(RequestDelegate next, IAuthenticationSchemeProvider schemas)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
if (context.Request.Headers.Keys.Contains("my-name"))
{
if (context.Request.Headers["my-name"].First().Equals("admin"))
{
ClaimsIdentity claimsIdentity = new ClaimsIdentity(new List<Claim>
{
new Claim(ClaimTypes.Name, "admin"),
new Claim(ClaimTypes.NameIdentifier, context.Request.Headers["my-id"].First()),
new Claim(ClaimTypes.Role, "Admin"),
new Claim("http://www.aspnetboilerplate.com/identity/claims/tenantId", "1", "int"),
new Claim("AspNet.Identity.SecurityStamp", Guid.NewGuid().ToString())
},
"Identity.Application");
ClaimsPrincipal principal = new ClaimsPrincipal(claimsIdentity);
context.User = principal;
await context.SignInAsync("Identity.Application", principal);
}
}
await _next(context);
}
}
所以,当我 运行 测试时我得到的是一个失败的测试。
Shouldly.ShouldAssertException : response.StatusCode
should be
HttpStatusCode.OK
but was HttpStatusCode.Redirect
我认为发生的情况是我们卡在了 [AbpMvcAuthorize]
功能中,并被重定向到登录页面。如果我从控制器中删除 AbpMvcAuthorize
,那么我会得到一个不同的失败状态。我收到空引用错误。 View
正在尝试渲染,但在调用 GetShownLoginName()
时在后续视图模型中失败:
public class SideBarUserAreaViewModel
{
public GetCurrentLoginInformationsOutput LoginInformations { get; set; }
public bool IsMultiTenancyEnabled { get; set; }
public string GetShownLoginName()
{
var userName = "<span id=\"HeaderCurrentUserName\">" + LoginInformations.User.UserName + "</span>";
if (!IsMultiTenancyEnabled)
{
return userName;
}
return LoginInformations.Tenant == null
? ".\" + userName
: LoginInformations.Tenant.TenancyName + "\" + userName;
}
}
我希望能够测试我的控制器逻辑,以确保对视图的更改、对视图模型的更改以及对服务的更改不会无意中导致页面加载错误。除了在我的 TestBase
class 中创建 UserManager
、LogInManager
和 SignInManager
的实例并以编程方式登录用户外,还有其他方法吗?
问题
- 您的
MyProjectWebTestBase
继承 AbpAspNetCoreIntegratedTestBase<TStartup>
.
AbpAspNetCoreIntegratedTestBase<TStartup>
使用 TestAbpSession
.
TestAbpSession
忽略声明。
解决方案
实现 MyTestAbpSession
,它依赖于 ClaimsAbpSession
。
public class MyTestAbpSession : TestAbpSession
{
public ClaimsAbpSession ClaimsAbpSession { get; set; }
public MyTestAbpSession(IMultiTenancyConfig multiTenancy,
IAmbientScopeProvider<SessionOverride> sessionOverrideScopeProvider,
ITenantResolver tenantResolver)
: base(multiTenancy, sessionOverrideScopeProvider, tenantResolver)
{
}
public override long? UserId
{
get => base.UserId ?? ClaimsAbpSession.UserId; // Fallback
set => base.UserId = value;
}
}
在MyProjectWebTestModule
的PreInitialize
方法中注册它。
public override void PreInitialize()
{
// ...
IocManager.IocContainer.Register(
Component.For<IAbpSession, TestAbpSession>()
.ImplementedBy<MyTestAbpSession>()
.LifestyleSingleton()
.IsDefault()
);
}
我正在尝试在我正在处理的新项目中建立单元测试。我正在使用 ASP.NET Boilerplate(.NET Core,多页面应用程序)和预构建的身份验证作为我的起点。自 InMemoryDatabase
进行测试的 Startup
class。但是,最基本的测试没有通过。我一直坚持拥有一个经过完全身份验证并被识别为 'logged in' 的测试用户。被测代码是这样的:
[AbpMvcAuthorize]
public class HomeController : ProjectControllerBase
{
public ActionResult Index()
{
return View();
}
}
测试是这样写的:
[Fact]
public async Task Index_Test()
{
// Added as part of suggestions made by 'https://medium.com/@zbartl/authentication-and-asp-net-core-integration-testing-using-testserver-15d47b03045a'
Client.DefaultRequestHeaders.Add("my-name", "admin");
Client.DefaultRequestHeaders.Add("my-id", "2");
// Act
var response = await GetResponseAsStringAsync(
GetUrl<HomeController>(nameof(HomeController.Index))
);
// Assert
response.ShouldNotBeNullOrEmpty();
}
引用 here 的博客允许我使用 Middleware
class 提供 ClaimsPrincipal
和 ClaimsIdentity
。中间件 class 看起来像这样:
public class TestAuthenticationMiddleware
{
private readonly RequestDelegate _next;
public TestAuthenticationMiddleware(RequestDelegate next, IAuthenticationSchemeProvider schemas)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
if (context.Request.Headers.Keys.Contains("my-name"))
{
if (context.Request.Headers["my-name"].First().Equals("admin"))
{
ClaimsIdentity claimsIdentity = new ClaimsIdentity(new List<Claim>
{
new Claim(ClaimTypes.Name, "admin"),
new Claim(ClaimTypes.NameIdentifier, context.Request.Headers["my-id"].First()),
new Claim(ClaimTypes.Role, "Admin"),
new Claim("http://www.aspnetboilerplate.com/identity/claims/tenantId", "1", "int"),
new Claim("AspNet.Identity.SecurityStamp", Guid.NewGuid().ToString())
},
"Identity.Application");
ClaimsPrincipal principal = new ClaimsPrincipal(claimsIdentity);
context.User = principal;
await context.SignInAsync("Identity.Application", principal);
}
}
await _next(context);
}
}
所以,当我 运行 测试时我得到的是一个失败的测试。
Shouldly.ShouldAssertException : response.StatusCode
should be
HttpStatusCode.OK
but was HttpStatusCode.Redirect
我认为发生的情况是我们卡在了 [AbpMvcAuthorize]
功能中,并被重定向到登录页面。如果我从控制器中删除 AbpMvcAuthorize
,那么我会得到一个不同的失败状态。我收到空引用错误。 View
正在尝试渲染,但在调用 GetShownLoginName()
时在后续视图模型中失败:
public class SideBarUserAreaViewModel
{
public GetCurrentLoginInformationsOutput LoginInformations { get; set; }
public bool IsMultiTenancyEnabled { get; set; }
public string GetShownLoginName()
{
var userName = "<span id=\"HeaderCurrentUserName\">" + LoginInformations.User.UserName + "</span>";
if (!IsMultiTenancyEnabled)
{
return userName;
}
return LoginInformations.Tenant == null
? ".\" + userName
: LoginInformations.Tenant.TenancyName + "\" + userName;
}
}
我希望能够测试我的控制器逻辑,以确保对视图的更改、对视图模型的更改以及对服务的更改不会无意中导致页面加载错误。除了在我的 TestBase
class 中创建 UserManager
、LogInManager
和 SignInManager
的实例并以编程方式登录用户外,还有其他方法吗?
问题
- 您的
MyProjectWebTestBase
继承AbpAspNetCoreIntegratedTestBase<TStartup>
. AbpAspNetCoreIntegratedTestBase<TStartup>
使用TestAbpSession
.TestAbpSession
忽略声明。
解决方案
实现
MyTestAbpSession
,它依赖于ClaimsAbpSession
。public class MyTestAbpSession : TestAbpSession { public ClaimsAbpSession ClaimsAbpSession { get; set; } public MyTestAbpSession(IMultiTenancyConfig multiTenancy, IAmbientScopeProvider<SessionOverride> sessionOverrideScopeProvider, ITenantResolver tenantResolver) : base(multiTenancy, sessionOverrideScopeProvider, tenantResolver) { } public override long? UserId { get => base.UserId ?? ClaimsAbpSession.UserId; // Fallback set => base.UserId = value; } }
在
MyProjectWebTestModule
的PreInitialize
方法中注册它。public override void PreInitialize() { // ... IocManager.IocContainer.Register( Component.For<IAbpSession, TestAbpSession>() .ImplementedBy<MyTestAbpSession>() .LifestyleSingleton() .IsDefault() ); }