测试控制器使用User.Identity.Name的Action

时间:2009-09-07 14:50:40

标签: asp.net-mvc unit-testing nunit moq

我有一个依赖于User.Identity.Name的动作来获取当前用户的用户名以获取他的订单列表:

public ActionResult XLineas()
    {
        ViewData["Filtre"] = _options.Filtre;
        ViewData["NomesPendents"] = _options.NomesPendents;
        return View(_repository.ObteLiniesPedido(User.Identity.Name,_options.Filtre,_options.NomesPendents));
    }

现在我正在尝试为此编写单元测试,但我不知道如何为User.Identity.Name提供模拟。如果我按照我的方式运行我的测试(没有模拟用户...),我得到一个Null ..例外。

这是正确的方法吗?我认为我的Action代码不适合单元测试。

2 个答案:

答案 0 :(得分:66)

您可以使用此代码

public SomeController CreateControllerForUser(string userName) 
{
    var mock = new Mock<ControllerContext>();
    mock.SetupGet(p => p.HttpContext.User.Identity.Name).Returns(userName);
    mock.SetupGet(p => p.HttpContext.Request.IsAuthenticated).Returns(true);

    var controller = new SomeController();
    controller.ControllerContext = mock.Object;

    return controller;
}

它使用Moq模拟框架,但你肯定可以使用任何你喜欢的东西。

答案 1 :(得分:21)

更好的方法是传递string参数userName(或IPrincipal参数user,如果您需要更多信息而不仅仅是名称)到ActionMethod,你使用ActionFilterAttribute在普通请求中“注入”。当你测试它时,你只需要提供你自己的模拟对象,因为动作过滤器的代码不会运行(在大多数情况下 - 如果你特别想要的话,还有办法...)

Kazi Manzur Ra​​shid在excellent blog post的第7点详细描述了这一点。