Solución:
HttpContext.Current
devuelve una instancia de System.Web.HttpContext
, que no se extiende System.Web.HttpContextBase
. HttpContextBase
se agregó más tarde a la dirección HttpContext
siendo difícil de burlarse. Básicamente, las dos clases no están relacionadas (HttpContextWrapper
se utiliza como adaptador entre ellos).
Afortunadamente, HttpContext
en sí mismo es lo suficientemente falso para que usted reemplace el IPrincipal
(Usuario) y IIdentity
.
El siguiente código se ejecuta como se esperaba, incluso en una aplicación de consola:
HttpContext.Current = new HttpContext(
new HttpRequest("", "http://tempuri.org", ""),
new HttpResponse(new StringWriter())
);
// User is logged in
HttpContext.Current.User = new GenericPrincipal(
new GenericIdentity("username"),
new string[0]
);
// User is logged out
HttpContext.Current.User = new GenericPrincipal(
new GenericIdentity(String.Empty),
new string[0]
);
Debajo de Test Init también hará el trabajo.
[TestInitialize]
public void TestInit()
{
HttpContext.Current = new HttpContext(new HttpRequest(null, "http://tempuri.org", null), new HttpResponse(null));
YourControllerToBeTestedController = GetYourToBeTestedController();
}
Sé que este es un tema más antiguo, sin embargo, simular una aplicación MVC para pruebas unitarias es algo que hacemos con mucha regularidad.
Solo quería agregar mis experiencias Simulando una aplicación MVC 3 usando Moq 4 después de actualizar a Visual Studio 2013. Ninguna de las pruebas unitarias funcionaba en modo de depuración y HttpContext mostraba “no se pudo evaluar la expresión” al intentar echar un vistazo a las variables .
Resulta que Visual Studio 2013 tiene problemas para evaluar algunos objetos. Para que las aplicaciones web simuladas de depuración funcionen nuevamente, tuve que marcar “Usar modo de compatibilidad administrada” en Herramientas => Opciones => Depuración => Configuración general.
Generalmente hago algo como esto:
public static class FakeHttpContext
{
public static void SetFakeContext(this Controller controller)
{
var httpContext = MakeFakeContext();
ControllerContext context =
new ControllerContext(
new RequestContext(httpContext,
new RouteData()), controller);
controller.ControllerContext = context;
}
private static HttpContextBase MakeFakeContext()
{
var context = new Mock<HttpContextBase>();
var request = new Mock<HttpRequestBase>();
var response = new Mock<HttpResponseBase>();
var session = new Mock<HttpSessionStateBase>();
var server = new Mock<HttpServerUtilityBase>();
var user = new Mock<IPrincipal>();
var identity = new Mock<IIdentity>();
context.Setup(c=> c.Request).Returns(request.Object);
context.Setup(c=> c.Response).Returns(response.Object);
context.Setup(c=> c.Session).Returns(session.Object);
context.Setup(c=> c.Server).Returns(server.Object);
context.Setup(c=> c.User).Returns(user.Object);
user.Setup(c=> c.Identity).Returns(identity.Object);
identity.Setup(i => i.IsAuthenticated).Returns(true);
identity.Setup(i => i.Name).Returns("admin");
return context.Object;
}
}
E iniciando el contexto así
FakeHttpContext.SetFakeContext(moController);
Y llamar al método en el controlador directamente
long lReportStatusID = -1;
var result = moController.CancelReport(lReportStatusID);