...但是当应用程序本身正在执行时,相同的扩展方法也可以工作。 UrlHelper扩展方法本身如下所示:
public static string CategoryLandingPage(this UrlHelper helper, string seoCategoryName)
{
return helper.RouteUrl("Category", new { area = "SoAndSo", controller = "SoAndSo", action = "Category", seoCategoryName = seoCategoryName }, "http");
}
我在SoAndSoAreaRegistration类中注册了这样的特定路由:
context.MapRoute(
"Category",
"category/{seoCategoryName}",
new { area = "SoAndSo", controller = "SoAndSo", action = "Category", seoCategoryName = string.Empty }
);
...我已经在该注册中删除了一个断点,以确保它被测试运行器击中,并且确实如此。
当我运行测试时,我得到一个ArgumentException,“在路径集合中找不到名为'Category'的路径。参数名称:name”。
我的猜测是我们不需要指定路线名称和足够的路线参数(区域/控制器/行动/类别名称)来完整地构建路线,因为我们在这里做,但我无法弄清楚路线名称在测试过程中消失的位置。删除类别名称可以消除异常并允许测试通过,但我仍然希望了解路由名称在测试时消失的位置。像这样简化代码仍然在运行时爆炸:
public static string CategoryLandingPage(this UrlHelper helper, string seoCategoryName)
{
return helper.RouteUrl("Category");
}
如果我在运行时挖掘路径集合,我可以找到类别路径,但没有.Name属性的证据,也没有看到路径的名称(带有大写C的“类别”) UrlHelper的属性(为愚蠢的混淆道歉;更好的安全而不是遗憾):
有没有人知道如何编写单元测试,这些测试会按照名称引用路由的UrlHelper扩展方法?谢谢!
更新 - 我将添加一些测试初始化,其中大部分是我从this popular question获得的,经过轻微修改以解释我正在使用的应用程序被分成多个MVC区域的事实:
private SoAndSoController CreateController() { var service = new Mock(); var cookieMgr = new Mock(); var logger = new Mock();
var allRoutes = new RouteCollection();
MvcApplication.RegisterRoutes(allRoutes);
var soAndSoAreaRegistration = new SoAndSoAreaRegistration();
var soAndSoAreaRegistrationContext = new AreaRegistrationContext(soAndSoAreaRegistration.AreaName, new RouteCollection());
soAndSoAreaRegistration.RegisterArea(soAndSoAreaRegistrationContext);
soAndSoAreaRegistrationContext.Routes.ForEach(r => allRoutes.Add(r));
var request = new Mock<HttpRequestBase>();
request.SetupGet(x => x.ApplicationPath).Returns("/");
request.SetupGet(x => x.Url).Returns(new Uri("http://localhost/a", UriKind.Absolute));
request.SetupGet(x => x.ServerVariables).Returns(new System.Collections.Specialized.NameValueCollection());
var response = new Mock<HttpResponseBase>();
response.Setup(x => x.ApplyAppPathModifier("/post1")).Returns("http://localhost/post1");
var context = new Mock<HttpContextBase>();
context.SetupGet(x => x.Request).Returns(request.Object);
context.SetupGet(x => x.Response).Returns(response.Object);
var controller = new SoAndSoController(service.Object, cookieMgr.Object, null, logger.Object, null);
controller.ControllerContext = new ControllerContext(context.Object, new RouteData(), controller);
controller.Url = new UrlHelper(new RequestContext(context.Object, new RouteData()), allRoutes);
return controller;
}
答案 0 :(得分:1)
我明白了。我需要将RouteCollection传递给AreaRegistrationContext,而不是传递一个新的RouteCollection:
var productFindingAreaRegistrationContext = new AreaRegistrationContext(productFindingAreaRegistration.AreaName, allRoutes);
但这导致这条线爆炸:
productFindingAreaRegistrationContext.Routes.ForEach(r => allRoutes.Add(r));
然而现在不再需要这条线,所以我评论了它。瞧。