Testing Routes in asp.net MVC
I'm using some code from Steve Sandersons MVC Framework book (2nd Ed.). I've got a class called Category that builds a RouteValueDictionary using it's other properties which I then use in the menu. On the site it works fine, the routing is correct and the links output as expceted. However, I'm tryng to create some test for them. Here's my Category class:
public class Category
{
public Category()
{
}
public Category(int id, string title, int sortOrder, int? parentId, bool isMainCategory, bool isVisible)
{
Id = id;
Title = title ?? "Home";
SortOrder = sortOrder;
ParentId = parentId;
IsMainCategory = isMainCategory;
IsVisible = isVisible;
}
private RouteValueDictionary routeValues;
public int Id { get; set; }
public string Title { get; set; }
public int? ParentId { get; set; }
public bool IsMainCategory { get; set; }
public bool IsVisible { get; set; }
public int SortOrder { get; set; }
public List<Category> SubCategories { get; set; }
public RouteValueDictionary RouteValues {
get
{
if (routeValues == null)
{
routeValues = new RouteValueDictionary(new
{
controller = "Products",
action = "Index",
cat = Id,
categoryName = UrlWorker.CleanUrl(Title)
//,
//page = 1,
//isParent = parent
});
}
return routeValues;
}
set
{
routeValues = value;
}
}
}
Here is the test I have set up:
[TestMethod]
public void CategoryGoesToCorrectRoute()
{
List<Category> list = categoryService.GetVisibleCategories();
Assert.AreEqual("/products/3/category-3", GenerateUrlViaMocks(new RouteValueDictionary(new
{
controller = "products",
action = "Index",
cat = 3,
categoryName = "category-3"
})));
//list[0].RouteValues));
}
And the GenerateUrlViaMocks method:
private string GenerateUrlViaMocks(object values)
{
// Arrange (get the routing config and test context)
RouteCollection routeConfig = new RouteCollection();
RegisterAllAreas(routeConfig);
MvcApplication.RegisterRoutes(routeConfig);
var mockContext = MakeMockHttpContext(null);
RouteData routeData = routeConfig.GetRouteData(mockContext.Object);
RequestContext context = new RequestContext(mockContext.Object, routeData);
// Act (genera开发者_开发知识库te a URL)
return UrlHelper.GenerateUrl(null, null, null,
new RouteValueDictionary(values), routeConfig, context, true);
}
Finally here is my routing table:
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute(
"SizeGuide",
"products/sizing",
new { controller = "products", action = "Sizing" },
new string[] { "EliteFightKit.Web.Controllers" }
);
routes.MapRoute(
"ViewCategory",
"products/{cat}/{categoryName}",
new { controller = "products", action = "Index", cat = 0, categoryName = "" },
new string[] { "EliteFightKit.Web.Controllers" }
);
routes.MapRoute(
"ViewProduct",
"products/{cat}/{id}/{productName}",
new { controller = "products", action = "Details", cat = "", id = "", productName = "" },
new string[] { "EliteFightKit.Web.Controllers" }
);
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Sitemap",
"sitemap",
new { controller = "Sitemap", action = "Index" }
);
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { action = "Index", id = "" },
new string[] { "EliteFightKit.Web.Controllers" }
);
routes.MapRoute(
"Root",
"",
new { controller = "Home", action = "Index", id = "" }
);
}
The problem I have is that the test actual result is coming back as /products/sizing?Count=4...
The ... is a bunch of url encoded 'code' that basically makes out it's a dictionary (sorry I can't print the actual error at the moment I'm away from the machine that enables me to run the tests). Given that this works on the website I figure this is a problem with the way I'm setting up in GenerateUrlViaMocks. The routeValues being passed into that method are correct so I'm really confused why it's not picking up on the fact I have a 'cat' and 'categoryName' parameter in my route parameters. Where am I going wrong?
Lloyd
I found the problem was on this line:
return UrlHelper.GenerateUrl(null, null, null,
new RouteValueDictionary(values), routeConfig, context, true);
The values, which were already a RouteValueDictionary, were being converted into another RouteValueDictionary. So all the properties such as Count, Keys, Values were being placed in as Key values in the next RVD.
I changed it to this:
return UrlHelper.GenerateUrl(null, null, null,
(RouteValueDictionary)values, routeConfig, context, true);
and it works. :)
Well, you don't specify a route name, so the "SizeGuide"
, which doesn't have a useful constraint, but does have defaults, is matched. That's probably wrong. You need to either specify a route name when calling GenerateUrl
or add constraints to the route.
精彩评论