I resolved this issue by mocking the ControllerContext so the controller "believed" it was being accessed by an authenticated user. Using the Moq mocking framework, this can be accomplished using the following mocking code:
var mockControllerContext = new Mock<ControllerContext>(); mockControllerContext .SetupGet(c => c.HttpContext.User.Identity.Name) .Returns("TestUser"); mockControllerContext .SetupGet(c => c.HttpContext.User.Identity.IsAuthenticated) .Returns(true); var homeController = new HomeController(); homeController.ControllerContext = mockControllerContext.Object;
This implementation does the job but it is not particularly readable at a glance. You have to read through each statement to understand which property the mock is setting up a return value for. Unit tests are a great way to understand the workings of a code base as they allow you to see at a high level how the code base is supposed to behave under certain circumstances. However, this benefit is dramatically reduced if the unit tests themselves are long winded and not easy to understand.
After watching Cory House’s Pluralsight course on Clean Code: Writing Code for Humans I have become acutely aware of the benefits of making your code more human readable. Extension methods are a good way to achieve a more readable syntax and led me to refactoring the above mocking code to the following:
var mockControllerContext = new Mock<ControllerContext>() .WithIdentityNameAs("testUser") .IsAuthenticated();
I was able to create this fluent syntax by creating a couple of extension methods that could be chained together to update the mocked ControllerContext object as required.
public static Mock<ControllerContext> WithIdentityNameAs( this Mock<ControllerContext> mockControllerContext, string username) { mockControllerContext .SetupGet(p => p.HttpContext.User.Identity.Name) .Returns(username); return mockControllerContext; } public static Mock<ControllerContext> IsAuthenticated( this Mock<ControllerContext> mockControllerContext) { mockControllerContext .SetupGet(p => p.HttpContext.User.Identity.IsAuthenticated) .Returns(true); return mockControllerContext; }
The key to writing extension methods that allow method chaining is to return the type which is passed in that the extension method extends. In the case of my extension methods, I had to return the mockControllerContext object or an instance of a Mock