[英]xunit - how to get HttpContext.User.Identity in unit tests
I added a method to my controllers to get the user-id from the JWT token in the HttpContext
.我在我的控制器中添加了一个方法来从
HttpContext
中的 JWT 令牌中获取用户 ID。 In my unit tests the HttpContext
is null , so I get an exception.在我的单元测试中,
HttpContext
是null ,所以我得到了一个异常。
How can I solve the problem?我该如何解决这个问题? Is there a way to moq the
HttpContext
?有没有办法起订量
HttpContext
?
Here is the method to get the user in my base controller这是在我的基础 controller 中获取用户的方法
protected string GetUserId()
{
if (HttpContext.User.Identity is ClaimsIdentity identity)
{
IEnumerable<Claim> claims = identity.Claims;
return claims.ToList()[0].Value;
}
return "";
}
One of my tests look like this我的一项测试看起来像这样
[Theory]
[MemberData(nameof(TestCreateUsergroupItemData))]
public async Task TestPostUsergroupItem(Usergroup usergroup)
{
// Arrange
UsergroupController controller = new UsergroupController(context, mapper);
// Act
var controllerResult = await controller.Post(usergroup).ConfigureAwait(false);
// Assert
//....
}
There really is no need to have to mock the HttpContext
in this particular case.在这种特殊情况下,确实没有必要模拟
HttpContext
。
Use the DefaultHttpContext
and set the members necessary to exercise the test to completion使用
DefaultHttpContext
并设置完成测试所需的成员
For example例如
[Theory]
[MemberData(nameof(TestCreateUsergroupItemData))]
public async Task TestPostUsergroupItem(Usergroup usergroup) {
// Arrange
//...
var identity = new GenericIdentity("some name", "test");
var contextUser = new ClaimsPrincipal(identity); //add claims as needed
//...then set user and other required properties on the httpContext as needed
var httpContext = new DefaultHttpContext() {
User = contextUser;
};
//Controller needs a controller context to access HttpContext
var controllerContext = new ControllerContext() {
HttpContext = httpContext,
};
//assign context to controller
UsergroupController controller = new UsergroupController(context, mapper) {
ControllerContext = controllerContext,
};
// Act
var controllerResult = await controller.Post(usergroup).ConfigureAwait(false);
// Assert
....
}
First of all, I would suggest you to use IHttpContextAccessor
to access HttpContext
and inject via Dependency Injection
instead of using HttpContext
directly.首先,我建议您使用
IHttpContextAccessor
访问HttpContext
并通过Dependency Injection
而不是直接使用HttpContext
进行注入。 You can follow this Microsoft documentation to understand usage and injection of IHttpContextAccessor
.您可以按照此 Microsoft 文档了解
IHttpContextAccessor
的用法和注入。
With the above code, your code will looks as follows to inject IHttpContextAccessor
使用上面的代码,您的代码将如下所示注入
IHttpContextAccessor
private IHttpContextAccessor httpContextAccessor;
public class UsergroupController(IHttpContextAccessor httpContextAccessor, ...additional parameters)
{
this.httpContextAccessor = httpContextAccessor;
//...additional assignments
}
Once IHttpContextAccessor
is injected, you can access the Identity as this.httpContextAccessor.HttpContext.User.Identity
注入
IHttpContextAccessor
,您可以通过this.httpContextAccessor.HttpContext.User.Identity
访问身份
So the GetUserId
should change as所以
GetUserId
应该改变为
protected string GetUserId()
{
if (this.httpContextAccessor.HttpContext.User.Identity is ClaimsIdentity identity)
{
IEnumerable<Claim> claims = identity.Claims;
return claims.ToList()[0].Value;
}
return "";
}
With above change, now you can easily inject the mock of IHttpContextAccessor
for unit testing.通过上述更改,现在您可以轻松地注入
IHttpContextAccessor
的模拟进行单元测试。 You can use the below code to create the mock:您可以使用以下代码创建模拟:
private static ClaimsPrincipal user = new ClaimsPrincipal(
new ClaimsIdentity(
new Claim[] { new Claim("MyClaim", "MyClaimValue") },
"Basic")
);
private static Mock<IHttpContextAccessor> GetHttpContextAccessor()
{
var httpContextAccessorMock = new Mock<IHttpContextAccessor>();
httpContextAccessorMock.Setup(h => h.HttpContext.User).Returns(user);
return httpContextAccessorMock;
}
With the above setup, in your test method, you can inject the mock of IHttpContextAccessor
while instantiating the object of UsergroupController
.通过上述设置,在您的测试方法中,您可以在实例化 UsergroupController 的
IHttpContextAccessor
的同时注入UsergroupController
的模拟。
As a follow up to the comment by @Nkosi: there's no requirement to DI the context as you can set it during testing like so:作为@Nkosi评论的后续:不需要DI上下文,因为您可以在测试期间设置它,如下所示:
var identity = new GenericIdentity("some name", "test");
var contextUser = new ClaimsPrincipal(identity);
controller.ControllerContext = new ControllerContext
{
HttpContext = new DefaultHttpContext { User = contextUser }
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.