10

我使用NUnitMoq库进行单元测试。我需要模拟重载的 Url.Action(string, string, object, string),因为我的控制器的操作使用它来获取 Action 的绝对网址

我现在的尝试(看看MockUrlAction测试):

[TestFixture]
public class ControllerTests   
{
    [Test]
    public void MockUrlAction()
    {
        var controller = new TestController();

        controller.Url = new UrlHelper(new RequestContext(MvcMoqHelpers.FakeHttpContext(), new RouteData()), GetRouteCollection());

        // it works
        Assert.AreEqual("/PathToAction", controller.Url.Action("TestAction")); 

        // but it doesn't work
        Assert.AreEqual("http://example.com/PathToAction", controller.Url.Action("TestAction", null, null, "http")); 
    }

    private RouteCollection GetRouteCollection()
    {
        BundleTable.MapPathMethod = MapBundleItemPath;
        var routes = new RouteCollection();
        RouteConfig.RegisterRoutes(routes);

        var adminArea = new AdminAreaRegistration();
        var adminAreaRegistrationContext = new AreaRegistrationContext(adminArea.AreaName, routes);
        adminArea.RegisterArea(adminAreaRegistrationContext);

        return routes;
    }
}

public static class MvcMoqHelpers
{
    public static HttpContextBase FakeHttpContext()
    {
        var context = new Mock<HttpContextBase>();
        var request = new Mock<HttpRequestBase>();
        var response = new Mock<HttpResponseBase>();
        var session = new Mock<HttpSessionStateBase>();
        var server = new Mock<HttpServerUtilityBase>();

        request.Setup(r => r.AppRelativeCurrentExecutionFilePath).Returns("/");
        request.Setup(r => r.ApplicationPath).Returns("/");
        response.Setup(s => s.ApplyAppPathModifier(It.IsAny<string>())).Returns<string>(s => s);

        context.Setup(ctx => ctx.Request).Returns(request.Object);
        context.Setup(ctx => ctx.Response).Returns(response.Object);
        context.Setup(ctx => ctx.Session).Returns(session.Object);
        context.Setup(ctx => ctx.Server).Returns(server.Object);

        return context.Object;
    }
}

并且在线

Assert.AreEqual("http://example.com/PathToAction", controller.Url.Action("TestAction", null, null, "http"));

我得到一个例外

System.NullReferenceException : Object reference not set to an instance of an object.
at System.Web.Mvc.UrlHelper.GenerateUrl(String routeName, String actionName, String controllerName, String protocol, String hostName, String fragment, RouteValueDictionary routeValues, RouteCollection routeCollection, RequestContext requestContext, Boolean includeImplicitMvcValues)
at System.Web.Mvc.UrlHelper.Action(String actionName, String controllerName, Object routeValues, String protocol)

对我来说很奇怪,它controller.Url.Action("TestAction")工作正常,但controller.Url.Action("TestAction", null, null, "http")没有。

PS MvcMoqHelpers.FakeHttpContext() 来自这里,也许它有助于回答这个问题。

所以问题是:我怎样才能得到 Url.Action(string, string, object, string) 的嘲笑?

谢谢。

4

1 回答 1

10

您必须设置 Request.Url,并且您在教程中提供了这段代码:

public static HttpContextBase FakeHttpContext(string url)
{
    HttpContextBase context = FakeHttpContext();
    context.Request.SetupRequestUrl(url);
    return context;
}

原因是 - 在您的 Url.Action 重载中,您没有提供主机名和协议,因此 MVC 尝试从 Request.Url 中提取这些值

if (!String.IsNullOrEmpty(protocol) || !String.IsNullOrEmpty(hostName))
{
    Uri requestUrl = requestContext.HttpContext.Request.Url;
    protocol = (!String.IsNullOrEmpty(protocol)) ? protocol : Uri.UriSchemeHttp;
    hostName = (!String.IsNullOrEmpty(hostName)) ? hostName : requestUrl.Host;
于 2013-03-06T22:03:31.800 回答