Asp.net mvc 2 UrlHelper';s RouteUrl在测试中返回空字符串

Asp.net mvc 2 UrlHelper';s RouteUrl在测试中返回空字符串,asp.net-mvc-2,asp.net-mvc-routing,Asp.net Mvc 2,Asp.net Mvc Routing,我遇到了一个问题,UrlHelper的RouteUrl方法在我的测试中运行时只返回一个空字符串,但在真正的HttpContext中执行时功能正常。然而,它是在寻找路由——如果我试图解析一个尚未定义的路由名称,我确实会得到一个异常 我已经使用模拟了HttpContext和friends,并将添加到模拟的实例中 为了减少我的情况中的变量数量,我编写了一个简单的测试: [测试] public void UrlHelperReturnsCorrectUrl() { var controller=new

我遇到了一个问题,UrlHelper的RouteUrl方法在我的测试中运行时只返回一个空字符串,但在真正的HttpContext中执行时功能正常。然而,它是在寻找路由——如果我试图解析一个尚未定义的路由名称,我确实会得到一个异常

我已经使用模拟了HttpContext和friends,并将添加到模拟的实例中

为了减少我的情况中的变量数量,我编写了一个简单的测试:

[测试]
public void UrlHelperReturnsCorrectUrl()
{
var controller=new MyController();
controller.SetFakeControllerContext().LoadUrlHelper();
AreEqual(“My/Route/Path”,controller.Url.RouteUrl(“MyRoute”);
}
有趣的是,直接访问RouteCollection并使用VirtualPath确实有效:

[测试]
public void GetVirtualPathReturnsCorrectUrl()
{
var controller=new AccountController();
controller.SetFakeControllerContext().LoadUrlHelper();
Assert.AreEqual(“我的/路线/路径”,
Controller.Url.RouteCollection[“MyRoute”]
.GetVirtualPath(
controller.Url.RequestContext,
新建RouteValueDictionary())
.VirtualPath);
}
以下是我对LoadUrlHelper扩展方法的实现,以供参考:

公共静态控制器LoadUrlHelper(此控制器)
{
var routes=new RouteCollection();
MVCAPApplication.RegisterRoutes(路由);
controller.Url=新的UrlHelper(
controller.ControllerContext.RequestContext,
路线);
返回控制器;
}
以下是我在应用程序的Global.asax中定义的路线:

routes.MapRoute(
“我的路线”、“我的/路线/路径”,
新建{controller=“Home”,action=“Index”});
有人碰到过这个吗?我错过什么了吗

编辑:

我一直在关注MVC代码,直到它将路由处理交给System.Routing,并发现了一些非常有趣的东西。MVC最终运行以查找所需URL的代码(当然是压缩的)返回一个空字符串:

Controller.Url.RouteCollection.GetVirtualPath(
Controller.Url.RequestContext,
“MyRoute”,新RouteValueDictionary()).VirtualPath;
而一个非常相似的变量返回预期的字符串:

Controller.Url.RouteCollection[“MyRoute”].GetVirtualPath(
Controller.Url.RequestContext,
新建RouteValueDictionary()).VirtualPath;

我似乎无法在底层代码中进一步了解这里实际发生的不同情况,但我认为这可能有助于了解我缺少的设置。(我还不想大喊bug,因为事实上UrlHelpers在真正的HttpContext中是可以工作的)

我的问题的解决方案已经发布到了

早些时候,我曾尝试将此解决方案整合到一顿饭中,但效果很差。一旦我完全复制了它,并根据我的情况进行了修改,它就完美地工作了

这里有一个更通用的版本,可以在许多测试中重用(如果放在基本测试夹具类或类似的东西中)

用法:

var controller=GetController();
controller.MyAction();
//...
方法:

protectedt GetController(),其中T:Controller,new()
{
var routes=new RouteCollection();
MVCAPApplication.RegisterRoutes(路由);
var request=newmock(MockBehavior.Strict);
SetupGet(x=>x.ApplicationPath)。返回(“/”;
SetupGet(x=>x.Url).Returns(新Uri(“http://localhost“,UriKind.Absolute”);
SetupGet(x=>x.ServerVariables).Returns(new System.Collections.Specialized.NameValueCollection());
var响应=新模拟(MockBehavior.Strict);
response.Setup(x=>x.ApplyAppPathModifier(It.IsAny())。返回((字符串p)=>p);
var context=newmock(MockBehavior.Strict);
SetupGet(x=>x.Request).Returns(Request.Object);
SetupGet(x=>x.Response).Returns(Response.Object);
var控制器=新的T();
controller.ControllerContext=新的ControllerContext(context.Object,new RouteData(),controller);
controller.Url=newurlhelper(newrequestcontext(context.Object,newroutedata()),routes);
返回控制器;
}

我的问题的解决方案已发布到

早些时候,我曾尝试将此解决方案整合到一顿饭中,但效果很差。一旦我完全复制了它,并根据我的情况进行了修改,它就完美地工作了

这里有一个更通用的版本,可以在许多测试中重用(如果放在基本测试夹具类或类似的东西中)

用法:

var controller=GetController();
controller.MyAction();
//...
方法:

protectedt GetController(),其中T:Controller,new()
{
var routes=new RouteCollection();
MVCAPApplication.RegisterRoutes(路由);
var request=newmock(MockBehavior.Strict);
SetupGet(x=>x.ApplicationPath)。返回(“/”;
SetupGet(x=>x.Url).Returns(新Uri(“http://localhost“,UriKind.Absolute”);
SetupGet(x=>x.ServerVariables).Returns(new System.Collections.Specialized.NameValueCollection());
var响应=新模拟(MockBehavior.Strict);
response.Setup(x=>x.ApplyAppPathModifier(It.IsAny())。返回((字符串p)=>p);
var context=newmock(MockBehavior.Strict);
SetupGet(x=>x.Request).Returns(Request.Object);
SetupGet(x=>x.Response).Returns(Response.Object);
var控制器=新的T();
controller.ControllerContext=新的ControllerContext(context.Object,new RouteData(),controller);
controller.Url=newurlhelper(newrequestcontext(context.Object,newroutedata()),routes);
返回控制器;
}

您想在这里测试什么?看起来你的测试正在进行