MVC Mock HttpContextBase 在助手中使用

发布于 2024-09-14 08:50:43 字数 2494 浏览 11 评论 0原文

我在我的控制器中使用了一个助手,并且在我的观点中,我在互联网上的某个地方找到了它。在我的控制器“Url.SiteRoot();”中像这样调用助手 如何让我的控制器在调用助手时不抛出异常?我正在使用 MVCContrib 和 moq 进行单元测试。

我正在考虑在帮助程序中实现某种检查,但感觉 MVCContrib 框架或起订量应该能够处理这个问题,这样我就不需要在我的帮助程序中添加异常代码只是为了能够通过单元测试。

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

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

I am using a helper in my controllers and in my views that I have found somewhere on the internet. The helper is called like this in my controller "Url.SiteRoot();"
How can I get my controller to not throw an Exception whenever the helper is called? I am using MVCContrib and moq for my unit tests.

I am thinking of implementing some kind of a check in the helper but it feel like the MVCContrib framework or the moq should be able to handle this so that I don't need to add Exception code in my helpers just to be able to pass the unit tests.

You can see the Helper code here:-

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

后eg是否自 2024-09-21 08:50:43

正如 @Jeremy Frey 所写,您会遇到异常,因为您未能存根/伪造 HttpContext 的一些重要部分。

不如使用:

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

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

As @Jeremy Frey writes you're getting the exceptions because you're failing to stub/fake some essential parts of the HttpContext.

How about using:

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

instead of trying to build the logic for building the url yourself? If I remember correctly it should pick up the protocol and port correctly, as well as any virtual directory, site, etc.

人生百味 2024-09-21 08:50:43

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

看看此处 有关如何模拟扩展方法调用的想法。我个人更喜欢这种策略,您是否重构了扩展方法以在运行时可交换。

例如,而不是

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 设置为模拟对象,但这样,您可以在测试时控制扩展方法的行为。

You've probably realized that the reason you're getting exceptions from your extension methods is due to unimplemented properties or methods on the mocked objects, e.g. Request on HttpContextBase, or RequestContext on UrlHelper.

Take a look at some of the strategies posted here for ideas on how to mock the extension method calls. I personally prefer this strategy, which would have you refactoring your extension methods to bet swappable at runtime.

For example, instead of:

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

}

You'd have:

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
    }
}

You'd need to change the way you'd call your extension methods, from urlHelper.GetReturnUrl() to urlHelper.Extensions().GetReturnUrl(), and during unit testing, you can set UrlHelperExtensions.UrlHelperExtensionFactory to a mocked object, but this way, you can control the extension methods' behavior at test time.

假装不在乎 2024-09-21 08:50:43

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

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

That code looks a little complicated. I think this does the same thing and would be much easier to test. (I'm not sure why it needs to be though.)

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文