如何使用moq模拟Controller.User

我有几个ActionMethods查询Controller.User的angular色是这样的

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

在这种情况下方便地行事。

我开始用这样的代码对这些方法进行testing

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

并且该testing失败,因为Controller.User未设置。 任何想法?

你需要模拟ControllerContext,HttpContextBase,最后是IPrincipal来模拟Controller上的用户属性。 使用Moq(v2)应该可以工作。

  [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"); } 

当用户不是pipe理员时testing行为与将userMock对象上的期望值设置为返回false一样简单。

使用Moq版本3.1(和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'"); } 

请注意,不需要为HttpContext创build模拟,Moq在设置testing时支持嵌套属性。