I added a method to my controllers to get the user-id from the JWT token in the HttpContext
. In my unit tests the HttpContext
is null, so I get an exception.
How can I solve the problem? Is there a way to moq the HttpContext
?
Here is the method to get the user in my base 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.
Use the DefaultHttpContext
and set the members necessary to exercise the test to completion
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. You can follow this Microsoft documentation to understand usage and injection of IHttpContextAccessor
.
With the above code, your code will looks as follows to inject 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
So the GetUserId
should change as
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. 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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With