【问题标题】:How-to test action filters in ASP.NET MVC?如何在 ASP.NET MVC 中测试动作过滤器?
【发布时间】:2010-11-06 15:57:45
【问题描述】:

需要一些指示。找到thisthis,但我还是有点困惑。

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

有什么帮助吗?

过滤器来源你可以找到here
(它发生了一些变化,但目前还不是重点)。

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

【问题讨论】:

  • ActionExecutedContext 派生自 ControllerContext。 Haacked 的回答正是关于模拟 ControllerContext - stackoverflow.com/questions/32640/…。你到底对什么感到困惑?
  • 只是还没做。我想我缺乏对 asp.net mvc 内部工作的了解。 :)
  • 然后发布您的代码。我们会尽力提供帮助:)

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


【解决方案1】:

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

这适用于 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);

【讨论】:

  • 如果您可以编辑单元测试形式的答案,我会很有帮助,请参阅@ArnisLapsa 答案。
【解决方案2】:

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

【讨论】:

  • rememberUrl 没有“ActionExecutedCotnext”方法。
  • 它是 OnActionExecuted。不管怎样——看来我终于明白了。只需要正确模拟httpContext。再次感谢 - 我非常感谢您的帮助。 :)
  • 任何想法如何测试这样的东西:gist.github.com/raw/88936/… ? :)
  • 我会从嘲笑ViewContext类开始
【解决方案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));
        }
    }
}

包装 Mock 以保持测试干净。

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

终于控制住了 HttpContext 怪物! ^^

【讨论】:

  • 如果它对你有用,那很酷,但是 xUnit 的人写了他们为什么要构建它,值得一读:xunit.codeplex.com/…
  • @richdiet 这是很久以前的事了。我现在更喜欢 xUnit。
猜你喜欢
  • 1970-01-01
  • 2012-08-04
  • 1970-01-01
  • 2017-04-18
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多