ASP.NET MVC: Mock controller.Url.Action

前端 未结 5 781
醉话见心
醉话见心 2020-12-14 02:03

Urls for menus in my ASP.NET MVC apps are generated from controller/actions. So, they call

controller.Url.Action(action, controller)

Now, h

相关标签:
5条回答
  • 2020-12-14 02:17

    Here's how you could mock UrlHelper using MvcContrib's 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));
    
    0 讨论(0)
  • 2020-12-14 02:22

    Here is another way to solve the problem with NSubstitute. Hope, it helps someone.

    // _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);
    
    0 讨论(0)
  • 2020-12-14 02:33

    A cleaner way to do this is just use Moq(or any other framework you like) to Mock UrlHelper itself

    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);
    

    clean and simple.

    0 讨论(0)
  • 2020-12-14 02:34

    Fake it easy works nicely:

     var fakeUrlHelper = A.Fake<UrlHelper>();
            controller.Url = fakeUrlHelper;
            A.CallTo(() => fakeUrlHelper.Action(A<string>.Ignored, A<string>.Ignored))
                .Returns("/Action/Controller");
    
    0 讨论(0)
  • 2020-12-14 02:36

    If you're using Moq (and not MvcContrib's TestControllerBuilder), you can mock out the context, similar to @DarianDimitrov's answer:

    var controller = new OrdersController();
    var context = new Mock<System.Web.HttpContextBase>().Object;
    
    controller.Url = new UrlHelper(
        new RequestContext(context, new RouteData()),
        new RouteCollection()
    );
    

    This doesn't set the controller.HttpContext property, but it does allow Url.Action to execute (and return an empty string -- no mocking required).

    0 讨论(0)
提交回复
热议问题