如何测试OnActionExecuted过滤器?

时间:2011-03-04 15:04:19

标签: unit-testing model-view-controller moq

所以我在我的BaseController类中重写OnActionExecuted以设置BaseViewModel的CurrentUser属性。我希望能够对此进行单元测试,但无法弄清楚如何。

以下是代码:

protected override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (filterContext.Result is ViewResult && ((ViewResult)filterContext.Result).ViewData.Model != null)
        {
            ((BaseViewModel)((ViewResult)filterContext.Result).ViewData.Model).CurrentUser = CurrentUser;
        }

        base.OnActionExecuted(filterContext);
    }

这是测试:

BaseController controller = new BaseController();
Mock<ActionExecutedContext> MockActionExecutedContext = new Mock<ActionExecutedContext>();
MockActionExecutedContext.Setup(ctx => ctx.Result).Returns(new ViewResult());
controllerAccessor.OnActionExecuted(MockActionExecutedContext.Object);

ViewResult vr = MockActionExecutedContext.Object.Result as ViewResult;
BaseViewModel model = vr.ViewData.Model as BaseViewModel;
User currentUser = model.CurrentUser;
Assert.NotNull(currentUser);

当我运行测试时,我收到错误:

System.NotSupportedException : Invalid setup on a non-virtual member: ctx => ctx.Result

我知道我可以在每个派生控制器的单元测试中测试属性,但必须有一个更简洁的方法来执行此操作。有什么想法吗?

1 个答案:

答案 0 :(得分:2)

我认为你不需要模拟ActionExecutedContext。只需创建一个实际的ActionExecutedContext即可传入控制器。我已经采取了许多自由,但考虑一下这个控制器代码:

 public class BaseController : Controller
{
    public User CurrentUser { get; set; }

    protected override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (filterContext.Result is ViewResult && ((ViewResult)filterContext.Result).ViewData.Model != null)
        {
            ((BaseViewModel)((ViewResult)filterContext.Result).ViewData.Model).CurrentUser = CurrentUser;
        }

        base.OnActionExecuted(filterContext);
    }

    public void controllerAccessor(ActionExecutedContext filterContext)
    {
        OnActionExecuted(filterContext);
    }
}

这个测试代码正在我的机器上运行:

 [TestMethod]
    public void YourTest()
    {
        // Arrange
        var inUser = new User();
        BaseController controller = new BaseController() { CurrentUser = inUser };
        var ctx = new ActionExecutedContext();
        var inVr = new ViewResult();
        var baseVm = new BaseViewModel();
        inVr.ViewData.Model = baseVm;
        ctx.Result = inVr;

        // Act
        controller.controllerAccessor(ctx);

        // Assert
        ViewResult outVr = (ViewResult)ctx.Result;
        BaseViewModel model = (BaseViewModel)outVr.ViewData.Model;
        User outUser = model.CurrentUser;
        Assert.AreEqual(inUser, outUser);
    }