使用模拟的控制器上下文来测试控制器

时间:2015-07-31 18:05:22

标签: c# asp.net-mvc unit-testing

我正在尝试对使用[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();
}

我觉得这是一个微不足道的修复,但我不知道我在做什么,所以这似乎是不可能的。

1 个答案:

答案 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.NameHttpContext.Request.IsAuthenticated,你添加以下lamda:

mock.SetupGet(x => x.HttpContext.User.Identity.IsAuthenticated).Returns(true);

此lamda将在控制器代码的if语句中生成true,成功模拟通过授权要求所需的条件。

事实证明我的控制器要求用户在数据库上...但除了错误之外,模拟工作绕过授权装饰并且非常容易。