How to mock Controller.User using moq

Eugenio Miró picture Eugenio Miró · Apr 16, 2009 · Viewed 25.3k times · Source

I have a couple of ActionMethods that queries the Controller.User for its role like this

bool isAdmin = User.IsInRole("admin");

acting conveniently on that condition.

I'm starting to make tests for these methods with code like this

[TestMethod]
public void HomeController_Index_Should_Return_Non_Null_ViewPage()
{
    HomeController controller  = new HomePostController();
    ActionResult index = controller.Index();

    Assert.IsNotNull(index);
}

and that Test Fails because Controller.User is not set. Any idea?

Answer

John Foster picture John Foster · Apr 16, 2009

You need to Mock the ControllerContext, HttpContextBase and finally IPrincipal to mock the user property on Controller. Using Moq (v2) something along the following lines should work.

    [TestMethod]
    public void HomeControllerReturnsIndexViewWhenUserIsAdmin() {
        var homeController = new HomeController();

        var userMock = new Mock<IPrincipal>();
        userMock.Expect(p => p.IsInRole("admin")).Returns(true);

        var contextMock = new Mock<HttpContextBase>();
        contextMock.ExpectGet(ctx => ctx.User)
                   .Returns(userMock.Object);

        var controllerContextMock = new Mock<ControllerContext>();
        controllerContextMock.ExpectGet(con => con.HttpContext)
                             .Returns(contextMock.Object);

        homeController.ControllerContext = controllerContextMock.Object;
        var result = homeController.Index();
        userMock.Verify(p => p.IsInRole("admin"));
        Assert.AreEqual(((ViewResult)result).ViewName, "Index");
    }

Testing the behaviour when the user isn't an admin is as simple as changing the expectation set on the userMock object to return false.