MVC Mock HttpContextBase,用于帮助程序

时间:2010-08-17 13:42:00

标签: c# asp.net-mvc asp.net-mvc-2 moq mvccontrib

我在控制器中使用帮助器,在我看来,我在互联网上找到了某个地方。帮助器在我的控制器“Url.SiteRoot();”中被调用。 每当调用帮助程序时,如何让我的控制器不抛出异常?我正在使用MVCContrib和moq进行单元测试。

我正在考虑在帮助器中实现某种检查,但感觉MVCContrib框架或moq应该能够处理这个,这样我就不需要在我的帮助器中添加Exception代码了通过单元测试。

您可以在此处查看帮助程序代码: -

namespace System.Web.Mvc {
public static class UrlHelpers {

    public static string SiteRoot(HttpContextBase context) {
        return SiteRoot(context, true);
    }

    public static string SiteRoot(HttpContextBase context, bool usePort) {
        var Port = context.Request.ServerVariables["SERVER_PORT"];
        if (usePort) {
            if (Port == null || Port == "80" || Port == "443")
                Port = "";
            else
                Port = ":" + Port;
        }
        var Protocol = context.Request.ServerVariables["SERVER_PORT_SECURE"];
        if (Protocol == null || Protocol == "0")
            Protocol = "http://";
        else
            Protocol = "https://";

        var appPath = context.Request.ApplicationPath;
        if (appPath == "/")
            appPath = "";

        var sOut = Protocol + context.Request.ServerVariables["SERVER_NAME"] + Port + appPath;
        return sOut;

    }

    public static string SiteRoot(this UrlHelper url) {
        return SiteRoot(url.RequestContext.HttpContext);
    }


    public static string SiteRoot(this ViewPage pg) {
        return SiteRoot(pg.ViewContext.HttpContext);
    }

    public static string SiteRoot(this ViewUserControl pg) {
        var vpage = pg.Page as ViewPage;
        return SiteRoot(vpage.ViewContext.HttpContext);
    }

    public static string SiteRoot(this ViewMasterPage pg) {
        return SiteRoot(pg.ViewContext.HttpContext);
    }

    public static string GetReturnUrl(HttpContextBase context) {
        var returnUrl = "";

        if (context.Request.QueryString["ReturnUrl"] != null) {
            returnUrl = context.Request.QueryString["ReturnUrl"];
        }

        return returnUrl;
    }

    public static string GetReturnUrl(this UrlHelper helper) {
        return GetReturnUrl(helper.RequestContext.HttpContext);
    }

    public static string GetReturnUrl(this ViewPage pg) {
        return GetReturnUrl(pg.ViewContext.HttpContext);
    }

    public static string GetReturnUrl(this ViewMasterPage pg) {
        return GetReturnUrl(pg.Page as ViewPage);
    }

    public static string GetReturnUrl(this ViewUserControl pg) {
        return GetReturnUrl(pg.Page as ViewPage);
    }
}
}

3 个答案:

答案 0 :(得分:2)

正如@Jeremy Frey写道,你得到了异常,因为你没有发现/伪造HttpContext的一些重要部分。

如何使用:

Request.Url.GetLeftPart(System.UriPartial.Authority) 

而不是尝试构建自己构建网址的逻辑?如果我没记错的话,它应该正确地选择协议和端口,以及任何虚拟目录,站点等。

答案 1 :(得分:0)

您可能已经意识到,您从扩展方法获取异常的原因是由于模拟对象上未实现的属性或方法,例如请求HttpContextBase或UrlHelper上的RequestContext。

查看有关如何模拟扩展方法调用的想法的here发布的一些策略。我个人更喜欢this strategy,这会让你重构你的扩展方法,以便在运行时下注。

例如,而不是:

public static class UrlHelperExtensions 
{
    public static string GetReturnUrl(this UrlHelper helper) 
    {
        return // your implementation of GetReturnUrl here
    }

}

你有:

public interface IUrlHelperExtensions 
{
    string GetReturnUrl(UrlHelper helper);
}

public static class UrlHelperExtensions
{
    public static IUrlHelperExtensions Extensions(this UrlHelper target)
    {
        return UrlHelperExtensionFactory(target);
    }

    static UrlExtensions 
    {
        UrlHelperExtensionFactory = () => new DefaultUrlHelperExtensionStrategy();
    }

    public static Func UrlHelperExtensionFactory { get; set; }
}   

public DefaultUrlHelperExtensionStrategy : IUrlHelperExtensions 
{
    public string GetReturnUrl(UrlHelper helper) 
    {
        return // your implementation of GetReturnUrl here
    }
}

您需要更改调用扩展方法的方式,从urlHelper.GetReturnUrl()到urlHelper.Extensions()。GetReturnUrl(),并且在单元测试期间,您可以将UrlHelperExtensions.UrlHelperExtensionFactory设置为模拟对象,但这样,您可以在测试时控制扩展方法的行为。

答案 2 :(得分:0)

该代码看起来有点复杂。我认为这会做同样的事情并且更容易测试。 (我不确定为什么它需要。)

public string FullApplicationPath(HttpRequestBase request)
{
    var path = request.Url.AbsoluteUri.Replace(request.Url.AbsolutePath,string.Empty);
    if (!string.IsNullOrEmpty(request.Url.Query))
    {
        path = path.Replace(request.Url.Query, string.Empty);
    }
    return path + request.ApplicationPath;
}