Asp.net mvc ASP.NET MVC:Mock controller.Url.Action

Asp.net mvc ASP.NET MVC:Mock controller.Url.Action,asp.net-mvc,Asp.net Mvc,my ASP.NET MVC应用程序中菜单的URL由控制器/操作生成。所以,他们打电话来 controller.Url.Action(action, controller) 现在,我如何在单元测试中实现这一点? 我成功地使用了MVCContrib var controller = new TestControllerBuilder().CreateController<OrdersController>(); var controller=newtestcontrollerbui

my ASP.NET MVC应用程序中菜单的URL由控制器/操作生成。所以,他们打电话来

controller.Url.Action(action, controller)
现在,我如何在单元测试中实现这一点? 我成功地使用了MVCContrib

var controller = new TestControllerBuilder().CreateController<OrdersController>();
var controller=newtestcontrollerbuilder().CreateController();
但无论我尝试用它做什么,我都会得到controller.Url.Action(Action,controller)以NullReferenceException失败,因为Url==null

更新:这与如何拦截HttpContext无关。我通过几种方式做到了这一点,使用了MVCContrib,Scott Hanselman的伪造示例,以及。这对我没有帮助,因为我需要知道要伪造什么值。。。是ApplicationPath吗?我如何设置它?它是否需要匹配被调用的控制器/操作?也就是说,Url.Action是如何工作的,我如何满足它


而且,我知道我可以做一些抽象的事情,并与之相适应。。。但我不确定我是否想这样做。毕竟,我拥有MVCContrib/Mock的全部功能,为什么我需要另一个抽象。

以下是如何使用MVCContrib的TestControllerBuilder模拟UrlHelper:

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));
var routes=newrouteCollection();
MVCAPApplication.RegisterRoutes(路由);
HomeController=CreateController();
controller.HttpContext.Response
.Stub(x=>x.ApplyAppPathModifier(“/Home/About”))
.Return(“/Home/About”);
controller.Url=新的UrlHelper(
新请求上下文(
controller.HttpContext,新路由数据()
), 
路线
);
var url=controller.url.Action(“关于”,“主页”);
Assert.IsFalse(string.IsNullOrEmpty(url));

假冒易用性很好:

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

如果您使用的是
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()
);
var controller=neworderscontroller();
var context=new Mock().Object;
controller.Url=新的UrlHelper(
新请求上下文(上下文,新路由数据()),
新路由集合()
);

这并没有设置controller.HttpContext属性,但它允许执行
Url.Action
(并返回一个空字符串——不需要模拟)。

一种更简洁的方法是使用Moq(或任何其他您喜欢的框架)模拟UrlHelper本身

var controller = new OrdersController();
var 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);
var controller=neworderscontroller();
var UrlHelperMock=new Mock();
controller.Url=UrlHelperMock.Object;
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);

干净、简单。

这里有另一种解决NSubstitute问题的方法。希望它能帮助别人

// _accountController is the controller that we try to test
var urlHelper = Substitute.For<UrlHelper>();
urlHelper.Action(Arg.Any<string>(), Arg.Any<object>()).Returns("/test_Controller/test_action");

var context = Substitute.For<HttpContextBase>();
_accountController.Url = urlHelper;
_accountController.ControllerContext = new ControllerContext(context, new RouteData(), _accountController);
/\u accountController是我们尝试测试的控制器
var urlHelper=Substitute.For();
Action(Arg.Any(),Arg.Any())。返回(“/test\u Controller/test\u Action”);
var context=Substitute.For();
_accountController.Url=urlHelper;
_accountController.ControllerContext=新的ControllerContext(上下文,新路由数据(),_accountController);

不值得单独给出答案,因此我将指出一个类似的答案:是的,我使用了该链接,但它不起作用。实际上,我尝试了Scott的版本和MVCContrib。我试图理解的是,我需要设置哪些值?Url.Action()实际使用的是什么?也就是说,在你提供的链接上有一个Moq版本,它设置了很多变量。。。所有这些都是必要的吗?我都试过了,但运气不好。请看有问题的更新…哦。。。在控制器的MSDN帮助中看到。Url“获取Url帮助对象”是一种误导。。。我甚至没有验证它是否有setter。你知道我们如何用MVC4达林实现这一点吗?由于我试图遵循您的代码示例,但无法调用RegisterRouteTyler:RegisterRoutes是一种约定,请使用mvcapApplication.RouteTable.Routes.Add(…)+1百万使用
FakeiTasy
!!但是
操作
方法不是虚拟的。。。那你怎么能伪造/截获呢?