我正在尝试对使用[Authorize]属性修饰的控制器运行单元测试。我在SO上找到的解决方案表明我应该使用Moq来模拟授权。解决方案code can be found here。
var controller = new UserController();
var mock = new Mock<ControllerContext>();
mock.SetupGet(x => x.HttpContext.User.Identity.Name).Returns("SOMEUSER");
mock.SetupGet(x => x.HttpContext.Request.IsAuthenticated).Returns(true);
controller.ControllerContext = mock.Object;
我在测试中实现了上述解决方案:
var controller = new HomeController();
var mock = new Mock<ControllerContext>();
mock.SetupGet(x => x.HttpContext.User.Identity.Name).Returns("SOMEUSER");
mock.SetupGet(x => x.HttpContext.Request.IsAuthenticated).Returns(true);
controller.ControllerContext = mock.Object;
var result = controller.GetStarted();
result.ExecuteResult(mock.Object);
Assert.IsTrue(false); //I am running with a breakpoint here
结果生成,但是当我尝试使用模拟的controllerContext执行结果时,我在行result.ExecuteResul...
处收到错误:NullReferenceException: object instance not set to an instance of an object
。
如何使用模拟的ControllerContext
来测试控制器?
控制器的骨架代码是:
[Authorize]
public ActionResult GetStarted()
{
if (User.Identity.IsAuthenticated)
{
var user = CommonUtil.Instance.UserManager.FindByName(User.Identity.Name);
if (user != null)
{
ViewBag.IsAdministrator = user.Roles.Contains("Administrators");
ViewBag.IsActiveUser = user.Roles.Contains("ActiveUsers");
}
}
return View();
}
我觉得这是一个微不足道的修复,但我不知道我在做什么,所以这似乎是不可能的。
答案 0 :(得分:1)
好的,想通了。如果其他人对Mocking来说是全新的,那真的很容易。
使用模拟库,您可以创建lambdas,表示对您正在模拟的对象的某些部分的调用。在我的例子中,我需要模拟对象User.Identity.IsAuthenticated
以便通过控制器中的if语句。
这仅仅意味着而不仅仅是代码,
var controller = new UserController();
var mock = new Mock<ControllerContext>();
mock.SetupGet(x => x.HttpContext.User.Identity.Name).Returns("SOMEUSER");
mock.SetupGet(x => x.HttpContext.Request.IsAuthenticated).Returns(true);
controller.ControllerContext = mock.Object;
其中
mock.SetupGet(x => x.HttpContext.User.Identity.Name).Returns("SOMEUSER");
mock.SetupGet(x => x.HttpContext.Request.IsAuthenticated).Returns(true);
...是你的lamdas,分别模拟对象特征HttpContext.User.Identity.Name
和HttpContext.Request.IsAuthenticated
,你添加以下lamda:
mock.SetupGet(x => x.HttpContext.User.Identity.IsAuthenticated).Returns(true);
此lamda将在控制器代码的if语句中生成true
,成功模拟通过授权要求所需的条件。
事实证明我的控制器要求用户在数据库上...但除了错误之外,模拟工作绕过授权装饰并且非常容易。