2012-03-22 5 views
11

MVCContrib TestHelperを使用してコントローラのユニットテストを行っています。MVCContribを使用してMVC 3コントローラとビューをユニット化するときにRouteDataにキーと値を追加する

単体テストでは、ここでは統合テストが本当に意味していますが、モデルが与えられれば私のビューがエラーなくレンダリングされていることを確認したいと思います...そうでなければ、基本的に関連するバグコントローラをテストしていても(モデルプロパティがnullの場合はレンダリングされないビューのように)モデルに追加する必要があります。

とにかく、私はこれを行う方法(別名、それを行う方法を探る)を理解しようとし始めました。 HTMLHelperを作成し、ビュー(この場合はpartial)をレンダリングするのが最も簡単な方法のようでした。

残念なことに、私が虚偽のHTMLHelperを使用しようとすると、ルートデータに使用可能なコントローラ名がないという不満があります。

確かに、私は見て、コントローラRouteDataは入力されていません。残念ながら、RouteData.Values RouteValueDictionaryは読み取り専用なので、必要な値を提供することはできません。

私は実際にビューをテストの一部としてレンダリングする問題を解決するためにHTMLHelperのアイデアと結婚していないので、そこに選択肢を提案しても構いませんが、Selenium、 Watinやその他のUIテストツール...私はUIベースのテストではできないテストのいくつかについて、状態やデータ情報を操作し復元するようなことをコントロールが遂行できるようにしたい。ここで

私は現在、部分的にレンダリングしようとする使用していたコードされています

public class FakeView : IView 
{ 
    #region IView Members 
    public void Render(ViewContext viewContext, System.IO.TextWriter writer) 
    { 
     throw new NotImplementedException(); 
    } 
    #endregion 
} 

public class WebTestUtilities 
{ 
    public static void prepareCache() 
    { 
     SeedDataManager seed = new SeedDataManager(); 
     seed.CheckSeedDataStatus(); 
    } 

    public static string RenderRazorViewToString(string viewName, object model, Controller controller) 
    { 
     var sb = new StringBuilder(); 
     var memWriter = new StringWriter(sb); 
     var html = new HtmlHelper(new ViewContext(controller.ControllerContext, 
      new FakeView(), new ViewDataDictionary(), new TempDataDictionary(), memWriter), 
      new ViewPage()); 
     //This fails because it can't extract route information like the controller name) 
     html.RenderPartial(viewName, model); 
     return sb.ToString(); 
    } 


    public void setupTestEnvironment(Controller controller) 
    { 
     RouteTable.Routes.Clear(); 
     RouteTable.Routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 

     RouteTable.Routes.MapRoute(
      "Default", 
      "{controller}/{action}/{id}", 
      new { controller = "Main", action = "DefaultView", id = UrlParameter.Optional } 
     ); 




     ModelBinders.Binders[typeof(DateTime)] = new DateTimeModelBinder(); 
     ModelBinders.Binders[typeof(DateTime?)] = new DateTimeModelBinder(); 
     ModelMetadataProviders.Current = new DateTimeMetadataProvider(); 



    } 
} 

そしてここでは、私の試験方法である:

 [TestMethod] 
    public void GetUserTableView() 
    { 
     ViewResult result = controller.UserTable() as ViewResult; 

     //I can populate the route and handler on the controller... 
     RouteData routes = RouteTable.Routes.GetRouteData(controller.HttpContext); 
     controller.RouteData.Route = routes.Route; 
     controller.RouteData.RouteHandler = routes.RouteHandler; 
     RouteValueDictionary routeKeys = new RouteValueDictionary(); 
     routeKeys.Add("controller", "UserManagement"); 
     routeKeys.Add("action", "UserTable"); 
     //But the RouteData.Values collection is read only :(
     controller.RouteData = new RouteData(){Values = routeKeys}; 
     string renderedView = WebTestUtilities.RenderRazorViewToString(result.ViewName, result.Model, controller); 
    } 

はところで、私が手に特定のエラーは、次のとおりです。 RouteDataには、文字列値が空でない 'controller'という項目が含まれている必要があります。

答えて

26

あなたはすでにこれを働いているかもしれませんが、私は同様の問題を抱えていたし、コントローラ上のControllerContextをリセットしてRouteDataを設定し解決そのように:あなたがテストに設定したとして

RouteData routeData = new RouteData(); 
routeData.Values.Add("someRouteDataProperty", "someValue"); 
ControllerContext controllerContext = new ControllerContext { RouteData = routeData }; 
controller.ControllerContext = controllerContext; 

、その後、コントローラRouteData.Values.ContainsKey(「someRouteDataProperty」)で動作します。

など

+0

素晴らしい、ありがとう。もちろん、アプリケーションの相対的な仮想パスを絶対にすることはできません "というエラーが発生するため、ビューへのパスを解決する方法を理解する必要がありますが、この部分は少なくとも機能しました。 – Amasuriel

2

コントローラControllerContext.RouteDataをオーバーライドすることができます。バーチャルRouteプロパティとRouteDataプロパティは、読み込み専用です。 asp.net MVC RouteDataプロパティの反映コードから

public RouteData RouteData 
{ 
    get 
    { 
     return ControllerContext == null ? null : ControllerContext.RouteData; 
    } 
} 
+0

をからかっしかし、その後、私は私は思わないだろう修正コントローラクラスを使用する必要ができるように、故意にありますControllerContextのパラメータなしのコンストラクタがありますので、これは動作します。 – Amasuriel

+0

いいえ、あなたはそれを必要としません – Sly

関連する問題