2012-05-08 11 views
5

T4MVCを使用するAsp.Net MVCアプリケーション用にWatinを使用してspecflowテストを作成しています。非Webアプリケーション(テスト)からのA​​sp.Net MVCルートの使用

私は自分自身が "魔法の文字列"のURLをテストで使用していることを知っています。私はそれが好きではありません。

[Given(@"I am on the sign up page")] 
public void GivenIAmOnTheSignUpPage() 
{ 
    string rootUrl = ConfigurationManager.AppSettings["RootUrl"]; 
    string fullUrl = string.Format("{0}/Authentication/Signup",rootUrl); 
    WebBrowser.Current.GoTo(fullUrl); 
} 
私は、MVCアプリケーションでは、このような何かを行うように私はむしろ私のT4MVCアクション結果を使用することになり

...何である

[Given(@"I am on the sign up page")] 
public void GivenIAmOnTheSignUpPage() 
{ 
    WebBrowser.Current.GoTo(MVC.Authentication.SignUp().ToAbsoluteUrl()); 
} 

マイToAbsoluteUrl拡張メソッド

public static class RouteHelper 
{ 
    private static UrlHelper _urlHelper; 
    private static string _rootUrl; 

    public static string ToAbsoluteUrl(this ActionResult result) 
    { 
     EnsureUrlHelperInitialized(); 

     var relativeUrl = _urlHelper.Action(result); 
     return string.Format("{0}/{1}", _rootUrl, relativeUrl); 
    } 

    private static void EnsureUrlHelperInitialized() 
    { 
     if (_urlHelper==null) 
     { 
      _rootUrl = ConfigurationManager.AppSettings["RootUrl"]; 

      var request = new HttpRequest("/", _rootUrl, ""); 
      var response = new HttpResponse(new StringWriter()); 
      var context = new HttpContext(request,response); 
      HttpContext.Current = context; 
      var httpContextBase = new HttpContextWrapper(context); 


      RouteTable.Routes.Clear(); 
      MvcApplication.RegisterRoutes(RouteTable.Routes); 

      var requestContext = new RequestContext(httpContextBase, RouteTable.Routes.GetRouteData(httpContextBase)); 

      _urlHelper = new UrlHelper(requestContext, RouteTable.Routes); 
     } 
    } 
} 

TestContextとRouteCollectionを初期化してテストURLを生成できる正しい方法?

現在、私はvar requestContext = new RequestContext(httpContextBase, RouteTable.Routes.GetRouteData(httpContextBase));行にNullReferenceExceptionを受け取ります。それはrequestContextを新規作成する正しい方法ですか?

またはActionResult(T4MVCから)を取り出し、Webアプリケーションの外部にある絶対URLに解決するより良い方法があれば、それは本当に私が探しているものです。

+0

SpecFlowでどのユニットテスト用libを使用していますか? MsTest、NUnitなど何か? – danludwig

+0

xUnitを使用していますが、それは重要ですか? – Brook

+0

いいえ、私は私の答えをカスタマイズすることができますかと思いました。私は[TestClass]と[AssemblyInitialize]のxunitに相当するものが何であるか分かりませんが、見つけ出すのは難しくないと思います。 – danludwig

答えて

5
public static class RouteHelper 
{ 
    private static UrlHelper _urlHelper; 
    private static string _rootUrl; 

    static RouteHelper() 
    { 
     var routes = new RouteCollection(); 
     MvcApplication.RegisterRoutes(routes); 
     var req = new HttpRequest(string.Empty, "http://www.site.com", null); 
     var res = new HttpResponse(null); 
     var ctx = new HttpContext(req, res); // do not use HttpContext.Current 
     var requestContext = new RequestContext(new HttpContextWrapper(ctx), 
      new RouteData()); 
     _urlHelper = new UrlHelper(requestContext, routes); 
     _rootUrl = ConfigurationManager.AppSettings["RootUrl"]; 
    } 

    public static string ToAbsoluteUrl(this ActionResult result) 
    { 
     return string.Format("{0}{1}", _rootUrl, _urlHelper.Action(result)); 
    } 
} 

静的コンストラクタは、プライベートフィールドを設定します。静的なRouteTable.Routesプロパティを使用する代わりに、新しいRouteCollectionを使用することを選択しましたが、可能性があります。

私はHttpRequestとHttpResponseのコンストラクタが問題ではないと思います。私はいくつかの文字列を渡して、例外を投げずに構築するようにしました。これらを使用して、新しいHttpContextを構築します(xUnitから実行する場合はHttpContext.Currentを使用しないでください)。その後、HttpContextBaseリファレンスを取得するためにHttpContextWrapperに配置することができます。

新しいRequestContextを作成し、ベースラッパーと新しいRouteDataインスタンスを渡します。以前のRouteCollectionとともにUrlHelperを構築してください。 Actionメソッドは "/"が付いた文字列を返しますので、RootUrl appSettingから離しておく必要があります(例:value = "https://develop.site.com"のようなものを末尾にスラッシュなしで使用してください)。

これは、MVC領域で定義されたルートでは機能しません。そのためには、グローバルasaxにRegisterRoutesを呼び出すことに加えて、その領域を登録する必要があります。

+0

それは、ありがとう、それをしました。私は、問題が発生したときに非常に奇妙な例外をスローする傾向があり、これが起こる可能性が高いconfigから読み込んでいるので、型初期化子の代わりに "Ensure"メソッドを使用するように変更しました。 – Brook

+0

あなたは何人の命を救う人ですか..私はこれを何時間も見つけました –

関連する問題