UrteHelper's RouteUrl возвращает пустую строку в тестах - PullRequest
1 голос
/ 04 августа 2010

У меня проблема с тем, что метод UrteHrl в UrlHelper возвращает только пустую строку при запуске в моих тестах, хотя работает правильно при выполнении в реальном HttpContext.Это, однако, поиск маршрута - поскольку я правильно получаю исключение, если я пытаюсь разрешить имя маршрута, которое не было определено.

Я издевался над HttpContext и друзьями, используя предоставленный код автор Scott Hanselman / Kzu и добавил код , необходимый для начальной загрузки маршрутов приложения в макетированный экземпляр

Чтобы уменьшить количество переменных в моей ситуации, я написал простойtest:

[Test]
public void UrlHelperReturnsCorrectUrl()
{
  var controller = new MyController();
  controller.SetFakeControllerContext().LoadUrlHelper();

  Assert.AreEqual("My/Route/Path", controller.Url.RouteUrl("MyRoute"));
}

Интересно, что прямой доступ к RouteCollection и использование VirtualPath работает:

[Test]
public void GetVirtualPathReturnsCorrectUrl()
{
    var controller = new AccountController();
    controller.SetFakeControllerContext().LoadUrlHelper();
    Assert.AreEqual("My/Route/Path", 
               Controller.Url.RouteCollection["MyRoute"]
               .GetVirtualPath(
                   controller.Url.RequestContext,
                   new RouteValueDictionary())
               .VirtualPath);
}

Для справки. Вот моя реализация метода расширения LoadUrlHelper:

public static Controller LoadUrlHelper(this Controller controller)
{
    var routes = new RouteCollection();
    MvcApplication.RegisterRoutes(routes);
    controller.Url = new UrlHelper(
                        controller.ControllerContext.RequestContext, 
                        routes);
    return controller;
}

А вот мой маршрут, как определено в Global.asax моего приложения:

routes.MapRoute(
   "MyRoute", "My/Route/Path",
   new {controller = "Home", action = "Index"});

Кто-нибудь сталкивался с этим?Я что-то упустил?

РЕДАКТИРОВАТЬ:

Я следовал коду MVC до такой степени, что он передает обработку маршрута в System.Routing и нашел что-то очень интересное.Код, который MVC в конечном итоге запускает для поиска нужного URL-адреса (сокращенно, конечно), возвращает пустую строку:

Controller.Url.RouteCollection.GetVirtualPath(
          Controller.Url.RequestContext, 
          "MyRoute", new RouteValueDictionary()).VirtualPath;

, тогда как чрезвычайно похожий вариант возвращает ожидаемую строку:

Controller.Url.RouteCollection["MyRoute"].GetVirtualPath(
          Controller.Url.RequestContext, 
          new RouteValueDictionary()).VirtualPath;

Кажется, я не могу идти дальше в базовом коде, чтобы увидеть, что на самом деле здесь происходит по-другому, но подумал, что это может помочь кому-то понять, какую настройку мне не хватает.(Я пока не собираюсь кричать об ошибке, поскольку факт, что UrlHelpers работает в реальном HttpContext, действительно работает)

1 Ответ

1 голос
/ 05 августа 2010

Решение моей проблемы уже было отправлено на другой вопрос SO .

Я пытался включить этот раствор по частям раньше, но сделал это плохо. Как только я полностью скопировал его и изменил для моей ситуации, он отлично работал.

Вот более общая версия, которую можно использовать во многих тестах (если она помещена в базовый класс тестовых приборов или что-то подобное).

Использование:

var controller = GetController<MyController>();
controller.MyAction();
//...

Метод:

protected T GetController<T>() where T : Controller, new()
{
    var routes = new RouteCollection();
    MvcApplication.RegisterRoutes(routes);

    var request = new Mock<HttpRequestBase>(MockBehavior.Strict);
    request.SetupGet(x => x.ApplicationPath).Returns("/");
    request.SetupGet(x => x.Url).Returns(new Uri("http://localhost", UriKind.Absolute));
    request.SetupGet(x => x.ServerVariables).Returns(new System.Collections.Specialized.NameValueCollection());

    var response = new Mock<HttpResponseBase>(MockBehavior.Strict);
    response.Setup(x => x.ApplyAppPathModifier(It.IsAny<string>())).Returns((string p) => p);

    var context = new Mock<HttpContextBase>(MockBehavior.Strict);
    context.SetupGet(x => x.Request).Returns(request.Object);
    context.SetupGet(x => x.Response).Returns(response.Object);

    var controller = new T();
    controller.ControllerContext = new ControllerContext(context.Object, new RouteData(), controller);
    controller.Url = new UrlHelper(new RequestContext(context.Object, new RouteData()), routes);

    return controller;
}
...