Solución:
Realmente no hay necesidad de burlarse del HttpContext
en este caso particular.
Utilizar el DefaultHttpContext
y establecer los miembros necesarios para realizar la prueba hasta su finalización
Por ejemplo
[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
....
}
En primer lugar, le sugiero que utilice IHttpContextAccessor
acceder HttpContext
e inyectar a través de Dependency Injection
En lugar de usar HttpContext
directamente. Puede seguir esta documentación de Microsoft para comprender el uso y la inyección de IHttpContextAccessor
.
Con el código anterior, su código se verá de la siguiente manera para inyectar IHttpContextAccessor
private IHttpContextAccessor httpContextAccessor;
public class UsergroupController(IHttpContextAccessor httpContextAccessor, ...additional parameters)
{
this.httpContextAccessor = httpContextAccessor;
//...additional assignments
}
Una vez IHttpContextAccessor
se inyecta, puede acceder a la identidad como this.httpContextAccessor.HttpContext.User.Identity
Entonces el GetUserId
debería cambiar como
protected string GetUserId()
{
if (this.httpContextAccessor.HttpContext.User.Identity is ClaimsIdentity identity)
{
IEnumerable<Claim> claims = identity.Claims;
return claims.ToList()[0].Value;
}
return "";
}
Con el cambio anterior, ahora puede inyectar fácilmente el simulacro de IHttpContextAccessor
para pruebas unitarias. Puede usar el siguiente código para crear el simulacro:
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;
}
Con la configuración anterior, en su método de prueba, puede inyectar el simulacro de IHttpContextAccessor
mientras instancia el objeto de UsergroupController
.