【问题标题】:Testing controller Action that uses User.Identity.Name测试使用 User.Identity.Name 的控制器操作
【发布时间】:2010-11-26 06:15:02
【问题描述】:

我有一个依赖 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 提供 Mock 的问题上。如果我按我的方式运行测试(没有对用户进行模拟...),我会得到一个 Null.. 异常。

什么是正确的方法?我认为我的操作代码不适合单元测试。

【问题讨论】:

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


    【解决方案1】:

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

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

    【讨论】:

    • 太棒了。我必须更多地研究 ActionFilters...谢谢。
    • 我经常为我的测试模拟 IPrincipal。它允许我测试用户信息(用户名)以及授权(User.Identity.IsInRole)。
    • 我也是。另一方面,模拟 IPrincipal 只是为了访问当前用户的用户名 - 而 nothing 其他 - 处于矫枉过正的边缘......: )
    • 传递 IPrincipal 或 IIdentity 对象时,您需要使用接口和包装器。仅使用 ActionFilter 会导致错误说您无法实现接口。
    • Kazi Manzur Ra​​shid 的文章提供了一个很好的起点。如果用户未经授权,我更喜欢修改代码以立即抛出 InvalidOperationException。另请注意,无论如何您都应该为 ActionFilterAttribute 编写单元测试,并且仍然必须至少模拟一次这些东西。
    【解决方案2】:

    你可以使用这个代码

    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 模拟框架,但确保你可以使用任何你喜欢的东西。

    【讨论】:

    • 对于像我这样想知道的其他人:此代码示例使用Moq
    • 在WebAPI中我确实喜欢这个MyController controller = new MyController(); controller.User = new GenericPrincipal(new GenericIdentity(username, "Passport"), new[] { "tester" });
    • @Ravi 怎么样? Controller.User is not settable(尽管这可能在过去 2.5 年发生了变化)
    • @Wolfzoon 我必须说实话。我不再使用 DotNet。不记得回答这个:-)。原谅我。
    猜你喜欢
    • 1970-01-01
    • 2011-01-08
    • 2013-01-28
    • 2014-09-29
    • 1970-01-01
    • 2020-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多