c# User.IsInRole 单元测试失败
c# User.IsInRole fails on unit test
我有这个方法:
[HttpPut]
[AuthorizeClaim("field:write")]
[ApiConventionMethod(typeof(AttemptApiConventions), nameof(AttemptApiConventions.AttemptPut))]
public override async Task<ActionResult<Field>> UpdateAsync(Field model)
{
var getAttempt = await Mediator.Send(new GenericGet<Field>(model.Id));
if (getAttempt.Failure) return Ok(getAttempt);
var field = getAttempt.Result;
if (!field.IsSpecification && !User.IsInRole("Administrator"))
return Ok(new ForbiddenError(string.Format(Resources.PermissionError, "this field")).ToAttempt<Field>());
if (!field.IsSpecification && model.Name != field.Name)
return Ok(new ValidationError(string.Format(Resources.CannotBeChanged, nameof(Field.Name))).ToAttempt<Field>());
return await base.UpdateAsync(model);
}
如您所见,我检查 User.IsInRole 在他们尝试更改字段时是否显示不同的错误消息。
问题是,我有这个单元测试:
[Test]
public async Task ReturnBadRequestIfSpecificationFieldNameChanges()
{
// Assemble
var model = new Field {Id = 1, IsSpecification = false, Name = "Test"};
var services = FieldsControllerContext.GivenServices();
var controller = services.WhenCreateController("Administrator");
services.Mediator.Send(Arg.Any<GenericGet<Field>>())
.Returns(new Field {Id = 1, IsSpecification = false, Name = "Old"});
// Act
var actionResult = await controller.UpdateAsync(model);
// Assert
actionResult.ShouldBeBadRequest(string.Format(Sxp.Web.Properties.Resources.CannotBeChanged, nameof(Field.Name)));
}
看看行 services.WhenCreateController("Administrator");
。它正在传递我希望模拟用户成为其成员的角色。这是这样设置的:
public static class ControllerExtensions
{
public static T WithUser<T>(this T controller, string roles = null) where T: ControllerBase
{
var id = Guid.NewGuid().ToString();
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, "example name"),
new Claim(ClaimTypes.NameIdentifier, id),
new Claim(JwtClaimTypes.Subject, id),
};
if (!string.IsNullOrEmpty(roles))
{
var r = roles.Split(",");
claims.AddRange(r.Select(role => new Claim(JwtClaimTypes.Role, role)));
}
var user = new ClaimsPrincipal(new ClaimsIdentity(claims, "mock"));
controller.ControllerContext = new ControllerContext
{
HttpContext = new DefaultHttpContext
{
User = user
}
};
return controller;
}
}
调试测试时,我可以看到:
谁能告诉我为什么?
我找到了答案。这行是罪魁祸首:
claims.AddRange(r.Select(role => new Claim(JwtClaimTypes.Role, role)));
它检查的不是 JwtClaimTypes
,它实际上检查的是:
"http://schemas.microsoft.com/ws/2008/06/identity/claims/role"
我有这个方法:
[HttpPut]
[AuthorizeClaim("field:write")]
[ApiConventionMethod(typeof(AttemptApiConventions), nameof(AttemptApiConventions.AttemptPut))]
public override async Task<ActionResult<Field>> UpdateAsync(Field model)
{
var getAttempt = await Mediator.Send(new GenericGet<Field>(model.Id));
if (getAttempt.Failure) return Ok(getAttempt);
var field = getAttempt.Result;
if (!field.IsSpecification && !User.IsInRole("Administrator"))
return Ok(new ForbiddenError(string.Format(Resources.PermissionError, "this field")).ToAttempt<Field>());
if (!field.IsSpecification && model.Name != field.Name)
return Ok(new ValidationError(string.Format(Resources.CannotBeChanged, nameof(Field.Name))).ToAttempt<Field>());
return await base.UpdateAsync(model);
}
如您所见,我检查 User.IsInRole 在他们尝试更改字段时是否显示不同的错误消息。 问题是,我有这个单元测试:
[Test]
public async Task ReturnBadRequestIfSpecificationFieldNameChanges()
{
// Assemble
var model = new Field {Id = 1, IsSpecification = false, Name = "Test"};
var services = FieldsControllerContext.GivenServices();
var controller = services.WhenCreateController("Administrator");
services.Mediator.Send(Arg.Any<GenericGet<Field>>())
.Returns(new Field {Id = 1, IsSpecification = false, Name = "Old"});
// Act
var actionResult = await controller.UpdateAsync(model);
// Assert
actionResult.ShouldBeBadRequest(string.Format(Sxp.Web.Properties.Resources.CannotBeChanged, nameof(Field.Name)));
}
看看行 services.WhenCreateController("Administrator");
。它正在传递我希望模拟用户成为其成员的角色。这是这样设置的:
public static class ControllerExtensions
{
public static T WithUser<T>(this T controller, string roles = null) where T: ControllerBase
{
var id = Guid.NewGuid().ToString();
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, "example name"),
new Claim(ClaimTypes.NameIdentifier, id),
new Claim(JwtClaimTypes.Subject, id),
};
if (!string.IsNullOrEmpty(roles))
{
var r = roles.Split(",");
claims.AddRange(r.Select(role => new Claim(JwtClaimTypes.Role, role)));
}
var user = new ClaimsPrincipal(new ClaimsIdentity(claims, "mock"));
controller.ControllerContext = new ControllerContext
{
HttpContext = new DefaultHttpContext
{
User = user
}
};
return controller;
}
}
调试测试时,我可以看到:
谁能告诉我为什么?
我找到了答案。这行是罪魁祸首:
claims.AddRange(r.Select(role => new Claim(JwtClaimTypes.Role, role)));
它检查的不是 JwtClaimTypes
,它实际上检查的是:
"http://schemas.microsoft.com/ws/2008/06/identity/claims/role"