C# 如何使用最小起订量模拟 Controller.User
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/758066/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to mock Controller.User using moq
提问by Eugenio Miró
I have a couple of ActionMethods that queries the Controller.User for its role like this
我有几个 ActionMethods 查询 Controller.User 的角色是这样的
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?
并且该测试失败,因为 Controller.User 未设置。任何的想法?
采纳答案by John Foster
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.
您需要模拟 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");
}
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.
测试用户不是管理员时的行为就像将 userMock 对象上的期望设置更改为返回 false 一样简单。
回答by Eirik W
Using Moq version 3.1 (and NUnit):
使用 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'");
}
Notice that there is no need to create mock for HttpContext, Moq supports nesting of properties when setting up the test.
请注意,不需要为 HttpContext 创建模拟,Moq 在设置测试时支持属性嵌套。
回答by Patrick
When using AspNetCore I could not mock the ControllerContext
since I got an exception.
使用 AspNetCore 时,我无法模拟,ControllerContext
因为我遇到了异常。
Unsupported expression: m => m.HttpContext
Non-overridable members (here: ActionContext.get_HttpContext) may not be used in setup / verification expressions.
不支持的表达式:m => m.HttpContext
不可覆盖成员(此处:ActionContext.get_HttpContext)不能用于设置/验证表达式。
Instead I had to mock the HttpContext
and create a ControllerContext
and pass the HttpContext
object along.
相反,我不得不模拟HttpContext
并创建一个ControllerContext
并传递HttpContext
对象。
I did find that mocking claims or response/request objects works as well when using this method.
我确实发现在使用此方法时,模拟声明或响应/请求对象也能正常工作。
[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);
}