I'm trying to add unit testing to an ASP.NET MVC application I have built. In my unit tests I use the following code:
[TestMethod]
public void IndexAction_Should_Return_View() {
var controller = new MembershipController();
controller.SetFakeControllerContext("TestUser");
...
}
With the following helpers to mock the controller context:
public static class FakeControllerContext {
public static HttpContextBase FakeHttpContext(string username) {
var context = new Mock<HttpContextBase>();
context.SetupGet(ctx => ctx.Request.IsAuthenticated).Returns(!string.IsNullOrEmpty(username));
if (!string.IsNullOrEmpty(username))
context.SetupGet(ctx => ctx.User.Identity).Returns(FakeIdentity.CreateIdentity(username));
return context.Object;
}
public static void SetFakeControllerContext(this Controller controller, string username = null) {
var httpContext = FakeHttpContext(username);
var context = new ControllerContext(new RequestContext(httpContext, new RouteData()), controller);
controller.ControllerContext = context;
}
}
This test class inherits from a base class which has the following:
[TestInitialize]
public void Init() {
...
}
Inside this method it calls a library (which i have no control over) which tries to run the following code:
HttpContext.Current.User.Identity.IsAuthenticated
Now you can probably see the problem. I have set the fake HttpContext against the controller but not in this base Init method. Unit testing / mocking is very new to me so I want to make sure I get this right. What is the correct way for me to Mock out the HttpContext so that it is shared across my controller and any libraries which are called in my Init method.
HttpContext.Current
returns an instance ofSystem.Web.HttpContext
, which does not extendSystem.Web.HttpContextBase
.HttpContextBase
was added later to addressHttpContext
being difficult to mock. The two classes are basically unrelated (HttpContextWrapper
is used as an adapter between them).Fortunately,
HttpContext
itself is fakeable just enough for you do replace theIPrincipal
(User) andIIdentity
.The following code runs as expected, even in a console application:
Below Test Init will also do the job.
If your application third party redirect internally, so it is better to mock HttpContext in below way :
I know this is an older subject, however Mocking a MVC application for unit tests is something we do on very regular basis.
I just wanted to add my experiences Mocking a MVC 3 application using Moq 4 after upgrading to Visual Studio 2013. None of the unit tests were working in debug mode and the HttpContext was showing "could not evaluate expression" when trying to peek at the variables.
Turns out visual studio 2013 has issues evaluating some objects. To get debugging mocked web applications working again, I had to check the "Use Managed Compatibility Mode" in Tools=>Options=>Debugging=>General settings.
I generally do something like this:
And initiating the context like this
And calling the Method in the controller straight forward