I have a controller action that automatically redirects to a new page if the user is already logged in (User.Identity.IsAuthenticated
). What is the best way to writ
I've been using the following Mocks with Moq to allow setting up various conditions in my unit tests. First, the HttpContextBase mock:
public static Mock GetHttpContextMock(bool isLoggedIn)
{
var context = new Mock();
var request = new Mock();
var response = new Mock();
var session = new Mock();
var server = new Mock();
var principal = AuthenticationAndAuthorization.GetPrincipleMock(isLoggedIn);
context.SetupGet(c => c.Request).Returns(request.Object);
context.SetupGet(c => c.Response).Returns(response.Object);
context.SetupGet(c => c.Session).Returns(session.Object);
context.SetupGet(c => c.Server).Returns(server.Object);
context.SetupGet(c => c.User).Returns(principal.Object);
return context;
}
Every property that might provide a useful Mock is set up in here. That way, if I need to add something like a referrer, I can just use:
Mock.Get(controller.Request).Setup(s => s.UrlReferrer).Returns(new Uri("http://blah.com/");
The "GetPrincipleMock" method is what sets up the user. It looks like this:
public static Mock GetPrincipleMock(bool isLoggedIn)
{
var mock = new Mock();
mock.SetupGet(i => i.Identity).Returns(GetIdentityMock(isLoggedIn).Object);
mock.Setup(i => i.IsInRole(It.IsAny())).Returns(false);
return mock;
}
public static Mock GetIdentityMock(bool isLoggedIn)
{
var mock = new Mock();
mock.SetupGet(i => i.AuthenticationType).Returns(isLoggedIn ? "Mock Identity" : null);
mock.SetupGet(i => i.IsAuthenticated).Returns(isLoggedIn);
mock.SetupGet(i => i.Name).Returns(isLoggedIn ? "testuser" : null);
return mock;
}
Now, my controller setups in the tests look like this:
var controller = new ProductController();
var httpContext = GetHttpContextMock(true); //logged in, set to false to not be logged in
ControllerContext controllerContext = new ControllerContext(httpContext.Object, new RouteData(), controller);
controller.ControllerContext = controllerContext;
It's a little bit of verbose setup, but once you have everything in place, testing a variety of conditions becomes a lot easier.