2010-12-15 82 views
2

如何为动作过滤器编写测试用例?我正在使用表单身份验证。 我有用RequiresAuthentication操作过滤器装饰的基础控制器。当我执行控制器的测试用例时,我没有从cookie中获取登录用户的数据。动作过滤器的ASP.NET MVC测试

我正在使用Moq;它是否提供了一种方法来实现我的目标?

+0

可能复制http://stackoverflow.com/questions/366388/how-can-i-unit-test-my-asp的-net-mvc-controller-that-uses-formsauthentication – rsenna 2010-12-15 12:26:25

+0

不,这不是我正在寻找的那个。我正在寻找可以使用Moq框架创建假htttpcontext的东西。 – nimi 2010-12-16 04:59:29

回答

2

blog post斯科特Hanselmann涵盖MvcMockHelpers包括等也起订量为FakeHttpContext不同嘲弄框架:

using System; 
using System.Web; 
using System.Text.RegularExpressions; 
using System.IO; 
using System.Collections.Specialized; 
using System.Web.Mvc; 
using System.Web.Routing; 
using Moq; 

namespace UnitTests 
{ 
    public static class MvcMockHelpers 
    { 
     public static HttpContextBase FakeHttpContext() 
     { 
      var context = new Mock<httpcontextbase>(); 
      var request = new Mock<httprequestbase>(); 
      var response = new Mock<httpresponsebase>(); 
      var session = new Mock<httpsessionstatebase>(); 
      var server = new Mock<httpserverutilitybase>(); 

      context.Expect(ctx => ctx.Request).Returns(request.Object); 
      context.Expect(ctx => ctx.Response).Returns(response.Object); 
      context.Expect(ctx => ctx.Session).Returns(session.Object); 
      context.Expect(ctx => ctx.Server).Returns(server.Object); 

      return context.Object; 
     } 

     public static HttpContextBase FakeHttpContext(string url) 
     { 
      HttpContextBase context = FakeHttpContext(); 
      context.Request.SetupRequestUrl(url); 
      return context; 
     } 

     public static void SetFakeControllerContext(this Controller controller) 
     { 
      var httpContext = FakeHttpContext(); 
      ControllerContext context = new ControllerContext(new RequestContext(httpContext, new RouteData()), controller); 
      controller.ControllerContext = context; 
     } 

     static string GetUrlFileName(string url) 
     { 
      if (url.Contains("?")) 
       return url.Substring(0, url.IndexOf("?")); 
      else 
       return url; 
     } 

     static NameValueCollection GetQueryStringParameters(string url) 
     { 
      if (url.Contains("?")) 
      { 
       NameValueCollection parameters = new NameValueCollection(); 

       string[] parts = url.Split("?".ToCharArray()); 
       string[] keys = parts[1].Split("&".ToCharArray()); 

       foreach (string key in keys) 
       { 
        string[] part = key.Split("=".ToCharArray()); 
        parameters.Add(part[0], part[1]); 
       } 

       return parameters; 
      } 
      else 
      { 
       return null; 
      } 
     } 

     public static void SetHttpMethodResult(this HttpRequestBase request, string httpMethod) 
     { 
      Mock.Get(request) 
       .Expect(req => req.HttpMethod) 
       .Returns(httpMethod); 
     } 

     public static void SetupRequestUrl(this HttpRequestBase request, string url) 
     { 
      if (url == null) 
       throw new ArgumentNullException("url"); 

      if (!url.StartsWith("~/")) 
       throw new ArgumentException("Sorry, we expect a virtual url starting with \"~/\"."); 

      var mock = Mock.Get(request); 

      mock.Expect(req => req.QueryString) 
       .Returns(GetQueryStringParameters(url)); 
      mock.Expect(req => req.AppRelativeCurrentExecutionFilePath) 
       .Returns(GetUrlFileName(url)); 
      mock.Expect(req => req.PathInfo) 
       .Returns(string.Empty); 
     } 
    } 
} 

另一个很好的资源,ASP.NET MVC测试助手是CodePlex上的MvcContrib项目。

之后,你有一个FakeHttpContext,你可以测试你的动作过滤器:

var context = new ActionExecutedContext(); 
context.HttpContext = MvcMockHelpers.FakeHttpContext(); 
context.Result = new EmpytResult(); // or whatever the default result should be 

var filter = new MyCustomAttribute(); 
filter.OnActionExecuted(context); 

Assert.True(context.Result is EmpytResult); 
... 
+0

任何人都知道为什么它需要一个虚拟的URL;有没有强制执行这个的很好理由? – 2012-02-07 21:27:16