MVC 自定义过滤器,手动调用 ASP.NET 管道事件进行单元测试
Posted
技术标签:
【中文标题】MVC 自定义过滤器,手动调用 ASP.NET 管道事件进行单元测试【英文标题】:MVC custom filter, invoke ASP.NET pipeline event manually for unit test 【发布时间】:2012-01-26 17:08:00 【问题描述】:public abstract class MyControllerBase : Controller
protected override void OnActionExecuting(ActionExecutingContext context)
// do some magic
我所有的控制器都继承自 MyControllerBase
。问题是现在我无法对某些方法进行单元测试,因为过滤器设置了一些影响代码路径的授权/逻辑标志。
有没有办法手动触发OnActionExecuting
?管道如何触发这些事件?
编辑:更多地展示这个设计背后的想法,以响应 cmets。我基本上是这样的:
public abstract class MyControllerBase : Controller
protected override void OnActionExecuting(ActionExecutingContext context)
UserProperties =
_userService
.GetUserProperties(filterContext.HttpContext.User.Identity.Name);
ViewBag.UserProperties = UserProperties;
public UserProperties get; private set;
public bool CheckSomethingAboutUser()
return UserProperties != null
&& UserProperties.IsAuthorisedToPerformThisAction;
// ... etc, other methods for querying UserProperties
所以现在在View
或Controller
的任何地方,我都可以获取当前用户的详细信息、他们的电子邮件地址、他们的授权、他们工作的部门等等。
例子:
public class PurchasingController : MyControllerBase
public ActionResult RaisePurchaseOrder(Item item)
// can use UserProperties from base class to determine correct action...
if (UserProperties.CanRaiseOrders)
if (UserProperties.Department == item.AllocatedDepartment)
所以这个设计真的很好用,但正如你所见,测试上述动作很困难,因为我无法在测试设置中直接操作UserProperties
。
【问题讨论】:
【参考方案1】:我不确定你是否应该像在 MCV 中那样覆盖 OnActionExecuting
,通常我会创建一个 ActionFilterAttribute
public class SomeMagicAttribute : ActionFilterAttribute
public override void OnActionExecuting(ActionExecutingContext filterContext)
那么你的班级:
[SomeMagic]
public abstract class MyControllerBase : Controller
然后在你的单元测试中你可以这样做
var magic = new SomeMagicAttribute();
var simulatedContext = new ActionExecutingContext();
magic.OnActionExecuting(simulatedContext);
【讨论】:
这里的问题是,在OnActionExecuting
事件中,我将一些标志写入ViewBag
和MyControllerBase
中的公共属性。这个想法是这些值现在在所有控制器和视图中随处可用。我的记忆有点模糊,但我想我选择了我的设计,因为我看不出使用自定义 ActionFilterAttribute
是如何实现的。你有什么想法吗?
你能发布一些你的OnActionExecuting
的魔法吗? - 至少要在 viewbag 中设置东西,你可以这样做filterContext.Controller.ViewBag.magic = 42;
我已更新问题以展示设计背后的理念。 OnActionExecuting
没有做任何聪明的事,它只是访问一些我想在全球范围内提供的用户信息。如果您认为我做错了,您的 cmets 将不胜感激。
不,你的做法没有错,事实上我只是检查了我正在处理的 MVC 项目,我们的做法非常相似。 - 无论如何,从您的代码示例来看,您似乎并不需要ActionExecutingContext
,因此您可以在基本构造函数中使用HttpContext.User.Identity.Name
填充UserProperties 变量,对吧?
不幸的是,这不起作用,因为HttpContext
在控制器构造函数中为空。以上是关于MVC 自定义过滤器,手动调用 ASP.NET 管道事件进行单元测试的主要内容,如果未能解决你的问题,请参考以下文章
asp.net mvc 中怎么像webform一样自定义一个BaseController实现判断用户是不是登录 然后获取用户的权限