我有一个依赖于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代码不适合单元测试。
答案 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 Rashid在excellent blog post的第7点详细描述了这一点。