如何测试ASP.NET MVC中的动作过滤器?

时间:2009-06-29 11:14:49

标签: asp.net-mvc testing action-filter

需要一些指针。找到thisthis,但我仍然感到困惑。

我只想模拟ActionExecutedContext,传递它,让过滤器稍微工作并检查结果。

任何帮助?

您可以找到的过滤器来源here
(它改变了一点,但目前不是重点)。

所以 - 我想要单元测试,RememberUrl过滤器足够智能,可以在会话中保存当前的URL。

3 个答案:

答案 0 :(得分:11)

1)在ActionExecutedContext中模拟Request.Url:

var request = new Mock<HttpRequestBase>();
request.SetupGet(r => r.HttpMethod).Returns("GET");
request.SetupGet(r => r.Url).Returns(new Uri("http://somesite/action"));

var httpContext = new Mock<HttpContextBase>();
httpContext.SetupGet(c => c.Request).Returns(request.Object);

var actionExecutedContext = new Mock<ActionExecutedContext>();
actionExecutedContext.SetupGet(c => c.HttpContext).Returns(httpContext.Object);

2)假设您在RememberUrlAttribute的公共构造函数中注入会话包装器。

var rememberUrl = new RememberUrlAttribute(yourSessionWrapper);

rememberUrl.OnActionExecuted(actionExecutedContext.Object);

// Then check what is in your SessionWrapper

答案 1 :(得分:3)

结果如下:

#region usages

using System;
using System.Collections.Specialized;
using System.Web;
using System.Web.Mvc;
using x.TestBase;
using x.UI.y.Infrastructure.Enums;
using x.UI.y.Infrastructure.Filters;
using x.UI.y.Test.Mocks;
using Moq;

//considering switch to NUnit... :D
using Microsoft.VisualStudio.TestTools.UnitTesting;

#endregion

namespace x.UI.y.Test.Unit.Infrastructure.Filters
{
    [TestClass]
    public class RememberUrlTester : TesterBase
    {
        private static HttpContextBaseMock _context = 
            new HttpContextBaseMock();
        private static ActionExecutedContextMock _actionContext = 
            new ActionExecutedContextMock(_context.Object);

        [TestMethod]
        //"Can save url in session" (i prefer test names in my own language :)
        public void SpeejPieglabaatUrlSesijaa()
        {
            //Arrange
            const string _url = "http://www.foo.bar/foo?bar=bar";
            _context.RequestMock.SetUrl(_url);    
            var filter = new RememberUrlAttribute();

            //Act
            filter.OnActionExecuted(_actionContext.Object);

            //Assert
            _context.SessionMock.Verify
                (m => m.Add(SessionKey.PreviousUrl.ToString(), _url));
        }
    }
}

Wrapped Mock&lt; HttpWhatever&gt;保持测试清洁。

我确信事情可以做得更好,但我认为这是一个很好的开始,我感到非常兴奋。

最后,HttpContext怪物得到了控制! ^^

答案 2 :(得分:0)

我知道这是一个老话题,但它可能有用。

这在 ASP.NET Core 2.1 中对我有用。我只想测试一个过滤器并在那里传递一个假的动作上下文。

object resultValue = 123;
var actionContext = new ActionContext(new DefaultHttpContext(), 
                                      new RouteData(), 
                                      new ActionDescriptor());

var context = new ActionExecutedContext(actionContext,
                                        new List<IFilterMetadata>(), 
                                        new object())
                                        {
                                            Result = new ObjectResult(resultValue)
                                        };

IActionFilter filter = new MyFilter();
filter.OnActionExecuted(context);