2010-12-15 83 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