我正在使用Watin编写specflow测试,用于使用T4MVC的Asp.Net MVC应用程序。
我发现自己在测试中使用了“魔术字符串”网址,我不喜欢。
[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 App中那样使用我的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);
}
}
}
初始化RequestContext和RouteCollection以便生成测试网址的正确方法是什么?
目前我在行var requestContext = new RequestContext(httpContextBase, RouteTable.Routes.GetRouteData(httpContextBase));
上收到NullReferenceException。这是新建requestContext的正确方法吗?
或者如果有一个更好的方法来获取ActionResult(来自T4MVC)并将其解析为绝对网址,在网络应用之外,这就是我正在寻找的。 p>
答案 0 :(得分: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));
}
}
静态构造函数设置您的私有字段。我选择使用新的RouteCollection,而不是使用静态的RouteTable.Routes属性,但您可以使用。
我认为HttpRequest和HttpResponse的构造函数不重要。我只是传入一些字符串来让它们构造而不抛出异常。使用它们构建一个全新的HttpContext(从xUnit运行时不要使用HttpContext.Current)。然后,您可以将其放入HttpContextWrapper中以获取HttpContextBase引用。
构造一个新的RequestContext,传入基础包装器和一个新的RouteData实例。使用它和您之前的RouteCollection来构造UrlHelper。请注意,其Action方法将返回前缀为“/”的字符串,因此您应该将其保留在RootUrl appSetting之外(因此请使用类似值=“https://develop.site.com”的内容而不使用尾部斜杠)。
请注意,这不适用于MVC区域中定义的路由。为此,除了在全局asax中调用RegisterRoutes之外,还需要注册这些区域。