Tuesday, 13 June 2017

c# - How to mock Controller.User using moq




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



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();

userMock.Expect(p => p.IsInRole("admin")).Returns(true);

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

var controllerContextMock = new Mock();
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.


No comments:

Post a Comment

c++ - Does curly brackets matter for empty constructor?

Those brackets declare an empty, inline constructor. In that case, with them, the constructor does exist, it merely does nothing more than t...