Подтвердить что ты не робот

ASP.NET MVC: Mock controller.Url.Action

URL-адреса в моих приложениях ASP.NET MVC генерируются из контроллера/действий. Таким образом, они называют

controller.Url.Action(action, controller)

Теперь, как мне сделать эту работу в модульных тестах? Я успешно использую MVCContrib с

var controller = new TestControllerBuilder().CreateController<OrdersController>();

но все, что я пытаюсь сделать с ним, я получаю control.Url.Action(действие, контроллер) с ошибкой NullReferenceException, потому что Url == null.

Обновление: это не о том, как перехватить HttpContext. Я сделал это несколькими способами, используя MVCContrib, пример фальсификации Скотта Хансельмана, а также один из http://stephenwalther.com/blog/archive/2008/07/01/asp-net-mvc-tip-12-faking-the-controller-context.aspx. Это не помогает мне, потому что мне нужно знать значения WHAT для подделки... это ApplicationPath? Как мне настроить его? Нужно ли соответствовать вызываемому контроллеру/действию? То есть, как работает Url.Action и как его удовлетворить?

Кроме того, я знаю, что могу выполнять IUrlActionAbstraction и идти с ним... но я не уверен, что хочу это сделать. В конце концов, у меня есть MVCContrib/Mock полная мощность и почему мне нужна другая абстракция.

4b9b3361

Ответ 1

Вот как вы могли бы издеваться над UrlHelper с помощью MvcContrib TestControllerBuilder:

var routes = new RouteCollection();
MvcApplication.RegisterRoutes(routes);
HomeController controller = CreateController<HomeController>();

controller.HttpContext.Response
    .Stub(x => x.ApplyAppPathModifier("/Home/About"))
    .Return("/Home/About");

controller.Url = new UrlHelper(
    new RequestContext(
        controller.HttpContext, new RouteData()
    ), 
    routes
);
var url = controller.Url.Action("About", "Home");
Assert.IsFalse(string.IsNullOrEmpty(url));

Ответ 2

Более чистый способ сделать это - просто использовать Moq (или любую другую структуру, которая вам нравится) для самого Mock UrlHelper

var controller = new OrdersController();
var Mock<UrlHelper> UrlHelperMock = new Mock<UrlHelper>();

controller.Url = UrlHelperMock.Object;

UrlHelperMock.Setup(x => x.Action("Action", "Controller", new {parem = "test"})).Returns("testUrl");

var url = controller.Url.Action("Action", "Controller", new {parem = "test"});
assert.areEqual("/Controller/Action/?parem=test",url);

чистый и простой.

Ответ 3

Подделка легко справляется:

 var fakeUrlHelper = A.Fake<UrlHelper>();
        controller.Url = fakeUrlHelper;
        A.CallTo(() => fakeUrlHelper.Action(A<string>.Ignored, A<string>.Ignored))
            .Returns("/Action/Controller");

Ответ 4

Если вы используете Moq (а не MvcContrib TestControllerBuilder), вы можете издеваться над контекстом, похожим на ответ @DarianDimitrov:

var controller = new OrdersController();
var context = new Mock<System.Web.HttpContextBase>().Object;

controller.Url = new UrlHelper(
    new RequestContext(context, new RouteData()),
    new RouteCollection()
);

Это не устанавливает свойство controller.HttpContext, но позволяет Url.Action выполнять (и возвращать пустую строку - не требует насмешек).