Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 708
Eugenio Miró Avatar asked Apr 16 '09 21:04

Eugenio Miró


People also ask

Can you mock a class with Moq?

You can use Moq to create mock objects that simulate or mimic a real object. Moq can be used to mock both classes and interfaces. However, there are a few limitations you should be aware of. The classes to be mocked can't be static or sealed, and the method being mocked should be marked as virtual.

Can you mock a private method Moq?

Moq supports mocking protected methods. Changing the methods to protected , instead of private , would allow you to mock their implementation.

What is Moq mocking framework?

Moq is a mocking framework built to facilitate the testing of components with dependencies. As shown earlier, dealing with dependencies could be cumbersome because it requires the creation of test doubles like fakes. Moq makes the creation of fakes redundant by using dynamically generated types.

Is Moq a testing framework?

The Moq framework is an open source unit testing framework that works very well with .


2 Answers

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.

like image 154
John Foster Avatar answered Oct 07 '22 09:10

John Foster


Using Moq version 3.1 (and NUnit):

    [Test]     public void HomeController_Index_Should_Return_Non_Null_ViewPage()     {         // Assign:         var homeController = new HomeController();          Mock<ControllerContext> controllerContextMock = new Mock<ControllerContext>();         controllerContextMock.Setup(             x => x.HttpContext.User.IsInRole(It.Is<string>(s => s.Equals("admin")))             ).Returns(true);         homeController.ControllerContext = controllerContextMock.Object;          // Act:         ActionResult index = homeController.Index();          // Assert:         Assert.IsNotNull(index);         // Place other asserts here...         controllerContextMock.Verify(             x => x.HttpContext.User.IsInRole(It.Is<string>(s => s.Equals("admin"))),             Times.Exactly(1),             "Must check if user is in role 'admin'");     } 

Notice that there is no need to create mock for HttpContext, Moq supports nesting of properties when setting up the test.

like image 27
Eirik W Avatar answered Oct 07 '22 09:10

Eirik W