Eug*_*iró 42 c# asp.net-mvc unit-testing moq mocking
我有几个ActionMethods来查询Controller.User这样的角色
bool isAdmin = User.IsInRole("admin");
Run Code Online (Sandbox Code Playgroud)
在这种情况下方便地行事.
我开始用这样的代码对这些方法进行测试
[TestMethod]
public void HomeController_Index_Should_Return_Non_Null_ViewPage()
{
HomeController controller = new HomePostController();
ActionResult index = controller.Index();
Assert.IsNotNull(index);
}
Run Code Online (Sandbox Code Playgroud)
并且测试失败,因为未设置Controller.User.任何的想法?
Joh*_*ter 69
你需要模拟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");
}
Run Code Online (Sandbox Code Playgroud)
当用户不是管理员时测试行为就像更改userMock对象上设置的期望值以返回false一样简单.
Eir*_*k W 22
使用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'");
}
Run Code Online (Sandbox Code Playgroud)
请注意,不需要为HttpContext创建模拟,Moq在设置测试时支持嵌套属性.
Pat*_*ick 11
使用 AspNetCore 时,我无法模拟,ControllerContext
因为我遇到了异常。
不支持的表达式:m => m.HttpContext
不可覆盖成员(此处:ActionContext.get_HttpContext)不能用于设置/验证表达式。
相反,我不得不模拟HttpContext
并创建一个ControllerContext
并传递HttpContext
对象。
我确实发现在使用此方法时,模拟声明或响应/请求对象也能正常工作。
[Test]
public void TestSomeStuff() {
var name = "some name";
var httpContext = new Mock<HttpContext>();
httpContext.Setup(m => m.User.IsInRole("RoleName")).Returns(true);
httpContext.Setup(m => m.User.FindFirst(ClaimTypes.Name)).Returns(name);
var context = new ControllerContext(new ActionContext(httpContext.Object, new RouteData(), new ControllerActionDescriptor()));
var controller = new MyController()
{
ControllerContext = context
};
var result = controller.Index();
Assert.That(result, Is.Not.Null);
}
Run Code Online (Sandbox Code Playgroud)